From b81c60e8a4e7783fe02c4bb710fcf324abc117f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw=20Chmiela?= Date: Thu, 7 Nov 2024 22:26:52 +0100 Subject: [PATCH] [eas-cli] Add `workflow:run` (#2669) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Why We want to allow users to start workflows manually. # How I added a `createRunMutation` to GraphQL and used it here. We upload project archive, `eas.json` and use to start a new workflow run. # Test Plan ``` Workflows are in beta and subject to breaking changes. Compressing project files and uploading to EAS. Learn more: https://expo.fyi/eas-build-archive ✔ Uploaded eas.json to EAS ✔ Uploaded project archive to EAS 1s ✔ Workflow started successfully. https://staging.expo.dev/accounts/sjchmiela/projects/staging-app/workflows/019301f1-b1b4-700d-9e3b-82dc97d76a32 ``` Co-authored-by: Szymon Dziedzic --- packages/eas-cli/graphql.schema.json | 2357 +++++++++++++++-- packages/eas-cli/src/build/utils/url.ts | 13 + packages/eas-cli/src/commands/workflow/run.ts | 115 + packages/eas-cli/src/graphql/generated.ts | 354 ++- .../mutations/UploadSessionMutation.ts | 38 + .../graphql/mutations/WorkflowRunMutation.ts | 55 + .../uploadAccountScopedEasJsonAsync.ts | 47 + .../uploadAccountScopedProjectSourceAsync.ts | 74 + packages/eas-cli/src/uploads.ts | 25 +- packages/eas-cli/src/utils/progress.ts | 3 +- 10 files changed, 2834 insertions(+), 247 deletions(-) create mode 100644 packages/eas-cli/src/commands/workflow/run.ts create mode 100644 packages/eas-cli/src/graphql/mutations/WorkflowRunMutation.ts create mode 100644 packages/eas-cli/src/project/uploadAccountScopedEasJsonAsync.ts create mode 100644 packages/eas-cli/src/project/uploadAccountScopedProjectSourceAsync.ts diff --git a/packages/eas-cli/graphql.schema.json b/packages/eas-cli/graphql.schema.json index 9185ad8553..f08a76e430 100644 --- a/packages/eas-cli/graphql.schema.json +++ b/packages/eas-cli/graphql.schema.json @@ -4193,6 +4193,23 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "ENUM", + "name": "AccountUploadSessionType", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "WORKFLOWS_PROJECT_SOURCES", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, { "kind": "OBJECT", "name": "AccountUsageEASBuildMetadata", @@ -8073,26 +8090,6 @@ "isDeprecated": false, "deprecationReason": null }, - { - "name": "filterReleaseChannels", - "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 - }, { "name": "filterTypes", "description": " Types of objects to filter ", @@ -10720,6 +10717,71 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "workflowRunsPaginated", + "description": null, + "args": [ + { + "name": "after", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "before", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "first", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "last", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "AppWorkflowRunsConnection", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "workflows", "description": null, @@ -13657,6 +13719,100 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "AppWorkflowRunEdge", + "description": null, + "fields": [ + { + "name": "cursor", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "WorkflowRun", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "AppWorkflowRunsConnection", + "description": null, + "fields": [ + { + "name": "edges", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "AppWorkflowRunEdge", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "AppleAppIdentifier", @@ -16552,6 +16708,22 @@ "name": "targetEntityTypeName", "description": null, "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityTypeName", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "targetEntityTypePublicName", + "description": null, + "args": [], "type": { "kind": "NON_NULL", "name": null, @@ -16927,6 +17099,30 @@ }, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "typeNamesMap", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "LogNameTypeMapping", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null } ], "inputFields": null, @@ -19698,6 +19894,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "fingerprintHash", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "fingerprintSource", "description": null, @@ -21328,6 +21536,18 @@ "description": null, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "LINUX_LARGE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "LINUX_MEDIUM", + "description": null, + "isDeprecated": false, + "deprecationReason": null } ], "possibleTypes": null @@ -22344,18 +22564,6 @@ "description": null, "fields": null, "inputFields": [ - { - "name": "environment", - "description": null, - "type": { - "kind": "ENUM", - "name": "EnvironmentVariableEnvironment", - "ofType": null - }, - "defaultValue": null, - "isDeprecated": false, - "deprecationReason": null - }, { "name": "environments", "description": null, @@ -22376,6 +22584,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "fileName", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "name", "description": null, @@ -23040,6 +23260,30 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "fileName", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "isGlobal", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "name", "description": null, @@ -23150,8 +23394,24 @@ "description": null, "fields": [ { - "name": "totals", - "description": "Totals from the beginning of time till now", + "name": "data", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "UpdatesMetricsData", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "metricsAtLastTimestamp", + "description": null, "args": [], "type": { "kind": "NON_NULL", @@ -23265,6 +23525,97 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "CumulativeUpdatesDataset", + "description": null, + "fields": [ + { + "name": "cumulative", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "difference", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "label", + "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": "INPUT_OBJECT", "name": "CustomBuildConfigInput", @@ -26165,115 +26516,115 @@ "interfaces": null, "enumValues": [ { - "name": "Account", + "name": "AccountEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "AccountSSOConfiguration", + "name": "AccountSSOConfigurationEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "AndroidAppCredentials", + "name": "AndroidAppCredentialsEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "AndroidKeystore", + "name": "AndroidKeystoreEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "App", + "name": "AppEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "AppStoreConnectApiKey", + "name": "AppStoreConnectApiKeyEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "AppleDevice", + "name": "AppleDeviceEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "AppleDistributionCertificate", + "name": "AppleDistributionCertificateEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "AppleProvisioningProfile", + "name": "AppleProvisioningProfileEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "AppleTeam", + "name": "AppleTeamEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "Branch", + "name": "BranchEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "Channel", + "name": "ChannelEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "Customer", + "name": "CustomerEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "GoogleServiceAccountKey", + "name": "GoogleServiceAccountKeyEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "IosAppCredentials", + "name": "IosAppCredentialsEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "UserInvitation", + "name": "UserInvitationEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "UserPermission", + "name": "UserPermissionEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "Workflow", + "name": "WorkflowEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "WorkflowRevision", + "name": "WorkflowRevisionEntity", "description": null, "isDeprecated": false, "deprecationReason": null @@ -26582,18 +26933,6 @@ "isDeprecated": false, "deprecationReason": null }, - { - "name": "environment", - "description": null, - "args": [], - "type": { - "kind": "ENUM", - "name": "EnvironmentVariableEnvironment", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, { "name": "environments", "description": null, @@ -26614,6 +26953,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "fileName", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "id", "description": null, @@ -26630,6 +26981,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "isGlobal", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "linkedEnvironments", "description": null, @@ -27384,18 +27747,6 @@ "isDeprecated": false, "deprecationReason": null }, - { - "name": "environment", - "description": null, - "args": [], - "type": { - "kind": "ENUM", - "name": "EnvironmentVariableEnvironment", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, { "name": "environments", "description": null, @@ -27416,6 +27767,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "fileName", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "id", "description": null, @@ -27432,6 +27795,22 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "isGlobal", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "linkedEnvironments", "description": null, @@ -34770,6 +35149,49 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "LogNameTypeMapping", + "description": null, + "fields": [ + { + "name": "publicName", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "typeName", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "EntityTypeName", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "LogsTimespan", @@ -34828,6 +35250,18 @@ "description": null, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "LAUNCH_PARTY_2024", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "NONPROD_EXPO_DEVELOPERS", + "description": null, + "isDeprecated": false, + "deprecationReason": null } ], "possibleTypes": null @@ -39415,6 +39849,22 @@ }, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "workflowRun", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "WorkflowRunMutation", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null } ], "inputFields": null, @@ -40232,6 +40682,22 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "workflowJobs", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "WorkflowJobQuery", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "workflowRevisions", "description": null, @@ -40248,6 +40714,22 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "workflowRuns", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "WorkflowRunQuery", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "workflows", "description": null, @@ -42229,6 +42711,22 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "sdkVersion", + "description": "SDK version of the snack", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "slug", "description": "Slug name, e.g. \"mysnack\", \"245631\"", @@ -46066,6 +46564,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "fileName", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "id", "description": null, @@ -46082,6 +46592,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "isGlobal", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "name", "description": null, @@ -46431,22 +46953,6 @@ { "name": "cumulativeMetrics", "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "CumulativeMetrics", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "cumulativeMetricsOverTime", - "description": null, "args": [ { "name": "timespan", @@ -46470,7 +46976,7 @@ "name": null, "ofType": { "kind": "OBJECT", - "name": "CumulativeMetricsOverTimeData", + "name": "CumulativeMetrics", "ofType": null } }, @@ -46918,11 +47424,127 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "UpdatesMetricsData", + "description": null, + "fields": [ + { + "name": "failedInstallsDataset", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CumulativeUpdatesDataset", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "installsDataset", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CumulativeUpdatesDataset", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "labels", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "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": "UploadSession", "description": null, "fields": [ + { + "name": "createAccountScopedUploadSession", + "description": "Create an Upload Session for a specific account", + "args": [ + { + "name": "accountID", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "AccountUploadSessionType", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "JSONObject", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "createUploadSession", "description": "Create an Upload Session", @@ -49464,6 +50086,22 @@ "name": "targetEntityTypeName", "description": null, "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "UserEntityTypeName", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "targetEntityTypePublicName", + "description": null, + "args": [], "type": { "kind": "NON_NULL", "name": null, @@ -49948,6 +50586,30 @@ }, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "typeNamesMap", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "UserLogNameTypeMapping", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null } ], "inputFields": null, @@ -50059,55 +50721,55 @@ "interfaces": null, "enumValues": [ { - "name": "AccessToken", + "name": "AccessTokenEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "DiscordUser", + "name": "DiscordUserEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "GitHubUser", + "name": "GitHubUserEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "Password", + "name": "PasswordEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "SSOUser", + "name": "SSOUserEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "User", + "name": "UserEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "UserPermission", + "name": "UserPermissionEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "UserSecondFactorBackupCodes", + "name": "UserSecondFactorBackupCodesEntity", "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "UserSecondFactorDevice", + "name": "UserSecondFactorDeviceEntity", "description": null, "isDeprecated": false, "deprecationReason": null @@ -50682,6 +51344,49 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "UserLogNameTypeMapping", + "description": null, + "fields": [ + { + "name": "publicName", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "typeName", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "UserEntityTypeName", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "UserPermission", @@ -53039,13 +53744,9 @@ "description": null, "args": [], "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Float", - "ofType": null - } + "kind": "SCALAR", + "name": "Float", + "ofType": null }, "isDeprecated": false, "deprecationReason": null @@ -54890,13 +55591,9 @@ "description": null, "args": [], "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Float", - "ofType": null - } + "kind": "SCALAR", + "name": "Float", + "ofType": null }, "isDeprecated": false, "deprecationReason": null @@ -55762,24 +56459,130 @@ "deprecationReason": null }, { - "name": "revisions", + "name": "revisionsPaginated", "description": null, - "args": [], + "args": [ + { + "name": "after", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "before", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "first", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "last", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "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": "WorkflowRevision", - "ofType": null - } - } + "kind": "OBJECT", + "name": "WorkflowRevisionsConnection", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "runsPaginated", + "description": null, + "args": [ + { + "name": "after", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "before", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "first", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "last", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "WorkflowRunsConnection", + "ofType": null } }, "isDeprecated": false, @@ -55809,99 +56612,79 @@ }, { "kind": "OBJECT", - "name": "WorkflowJobMutation", + "name": "WorkflowJob", "description": null, "fields": [ { - "name": "approveWorkflowJob", + "name": "createdAt", "description": null, - "args": [ - { - "name": "workflowJobId", - "description": null, - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "defaultValue": null, - "isDeprecated": false, - "deprecationReason": null - } - ], + "args": [], "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "ID", + "name": "DateTime", "ofType": null } }, "isDeprecated": false, "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "WorkflowQuery", - "description": "Look up Workflow by ID", - "fields": [ + }, { - "name": "byId", + "name": "credentialsAppleDeviceRegistrationRequest", "description": null, - "args": [ - { - "name": "workflowId", - "description": null, - "type": { + "args": [], + "type": { + "kind": "OBJECT", + "name": "AppleDeviceRegistrationRequest", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { "kind": "NON_NULL", "name": null, "ofType": { - "kind": "SCALAR", - "name": "ID", + "kind": "OBJECT", + "name": "WorkflowJobError", "ofType": null } - }, - "defaultValue": null, - "isDeprecated": false, - "deprecationReason": null + } } - ], + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], "type": { "kind": "NON_NULL", "name": null, "ofType": { - "kind": "OBJECT", - "name": "Workflow", + "kind": "SCALAR", + "name": "ID", "ofType": null } }, "isDeprecated": false, "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "WorkflowRevision", - "description": null, - "fields": [ + }, { - "name": "blobSha", + "name": "key", "description": null, "args": [], "type": { @@ -55917,7 +56700,7 @@ "deprecationReason": null }, { - "name": "commitSha", + "name": "name", "description": null, "args": [], "type": { @@ -55933,7 +56716,7 @@ "deprecationReason": null }, { - "name": "createdAt", + "name": "outputs", "description": null, "args": [], "type": { @@ -55941,7 +56724,7 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "DateTime", + "name": "JSONObject", "ofType": null } }, @@ -55949,7 +56732,99 @@ "deprecationReason": null }, { - "name": "id", + "name": "requiredJobKeys", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "status", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "WorkflowJobStatus", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "turtleBuild", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "Build", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "turtleJobRun", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "JobRun", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "turtleSubmission", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "Submission", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "WorkflowJobType", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updatedAt", "description": null, "args": [], "type": { @@ -55957,7 +56832,7 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "ID", + "name": "DateTime", "ofType": null } }, @@ -55965,7 +56840,7 @@ "deprecationReason": null }, { - "name": "workflow", + "name": "workflowRun", "description": null, "args": [], "type": { @@ -55973,7 +56848,34 @@ "name": null, "ofType": { "kind": "OBJECT", - "name": "Workflow", + "name": "WorkflowRun", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "WorkflowJobError", + "description": null, + "fields": [ + { + "name": "message", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", "ofType": null } }, @@ -55981,7 +56883,7 @@ "deprecationReason": null }, { - "name": "yamlConfig", + "name": "title", "description": null, "args": [], "type": { @@ -56002,6 +56904,509 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "WorkflowJobMutation", + "description": null, + "fields": [ + { + "name": "approveWorkflowJob", + "description": null, + "args": [ + { + "name": "workflowJobId", + "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": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "WorkflowJobQuery", + "description": null, + "fields": [ + { + "name": "byId", + "description": null, + "args": [ + { + "name": "workflowJobId", + "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": "WorkflowJob", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "WorkflowJobStatus", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "ACTION_REQUIRED", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "CANCELED", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "FAILURE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "IN_PROGRESS", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "NEW", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SKIPPED", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SUCCESS", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "WorkflowJobType", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "APPLE_DEVICE_REGISTRATION_REQUEST", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "BUILD", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "CUSTOM", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "MAESTRO_TEST", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "REQUIRE_APPROVAL", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SUBMISSION", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "UPDATE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "WorkflowProjectSourceInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "easJsonBucketKey", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "projectArchiveBucketKey", + "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": "WorkflowProjectSourceType", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "WorkflowProjectSourceType", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "GCS", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "WorkflowQuery", + "description": "Look up Workflow by ID", + "fields": [ + { + "name": "byId", + "description": null, + "args": [ + { + "name": "workflowId", + "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": "Workflow", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "WorkflowRevision", + "description": null, + "fields": [ + { + "name": "blobSha", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "commitSha", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "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": "workflow", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Workflow", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "yamlConfig", + "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": "WorkflowRevisionEdge", + "description": null, + "fields": [ + { + "name": "cursor", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "WorkflowRevision", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "WorkflowRevisionInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "fileName", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "yamlConfig", + "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": "OBJECT", "name": "WorkflowRevisionQuery", @@ -56046,6 +57451,560 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "WorkflowRevisionsConnection", + "description": null, + "fields": [ + { + "name": "edges", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "WorkflowRevisionEdge", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "WorkflowRun", + "description": null, + "fields": [ + { + "name": "createdAt", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "DateTime", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "gitCommitHash", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "gitCommitMessage", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "githubRepository", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "GitHubRepository", + "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": "initiatingUser", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "jobs", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "WorkflowJob", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pullRequestNumber", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "requestedGitRef", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "status", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "WorkflowRunStatus", + "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 + }, + { + "name": "workflow", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Workflow", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "workflowRevision", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "WorkflowRevision", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "WorkflowRunEdge", + "description": null, + "fields": [ + { + "name": "cursor", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "WorkflowRun", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "WorkflowRunInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "projectSource", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "WorkflowProjectSourceInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "WorkflowRunMutation", + "description": null, + "fields": [ + { + "name": "createWorkflowRun", + "description": null, + "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": "workflowRevisionInput", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "WorkflowRevisionInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "workflowRunInput", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "WorkflowRunInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "WorkflowRun", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "WorkflowRunQuery", + "description": null, + "fields": [ + { + "name": "byId", + "description": null, + "args": [ + { + "name": "workflowRunId", + "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": "WorkflowRun", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "WorkflowRunStatus", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "ACTION_REQUIRED", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "CANCELED", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "FAILURE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "IN_PROGRESS", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "NEW", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SUCCESS", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "WorkflowRunsConnection", + "description": null, + "fields": [ + { + "name": "edges", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "WorkflowRunEdge", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "__Directive", diff --git a/packages/eas-cli/src/build/utils/url.ts b/packages/eas-cli/src/build/utils/url.ts index dd8bd55181..b72f683db0 100644 --- a/packages/eas-cli/src/build/utils/url.ts +++ b/packages/eas-cli/src/build/utils/url.ts @@ -50,3 +50,16 @@ export function getUpdateGroupUrl( getExpoWebsiteBaseUrl() ).toString(); } + +export function getWorkflowRunUrl( + accountName: string, + projectName: string, + workflowRunId: string +): string { + return new URL( + `/accounts/${encodeURIComponent(accountName)}/projects/${encodeURIComponent( + projectName + )}/workflows/${workflowRunId}`, + getExpoWebsiteBaseUrl() + ).toString(); +} diff --git a/packages/eas-cli/src/commands/workflow/run.ts b/packages/eas-cli/src/commands/workflow/run.ts new file mode 100644 index 0000000000..b412326e9b --- /dev/null +++ b/packages/eas-cli/src/commands/workflow/run.ts @@ -0,0 +1,115 @@ +import fs from 'node:fs'; +import * as path from 'node:path'; + +import { getWorkflowRunUrl } from '../../build/utils/url'; +import EasCommand from '../../commandUtils/EasCommand'; +import { EASNonInteractiveFlag } from '../../commandUtils/flags'; +import { WorkflowProjectSourceType } from '../../graphql/generated'; +import { WorkflowRunMutation } from '../../graphql/mutations/WorkflowRunMutation'; +import Log, { link } from '../../log'; +import { getOwnerAccountForProjectIdAsync } from '../../project/projectUtils'; +import { uploadAccountScopedEasJsonAsync } from '../../project/uploadAccountScopedEasJsonAsync'; +import { uploadAccountScopedProjectSourceAsync } from '../../project/uploadAccountScopedProjectSourceAsync'; + +export default class WorkflowRun extends EasCommand { + static override description = 'Run an EAS workflow'; + + // TODO(@sjchmiela): Keep command hidden until workflows are live + static override hidden = true; + static override state = 'beta'; + + static override args = [{ name: 'file', description: 'Path to the workflow file to run' }]; + + static override flags = { + ...EASNonInteractiveFlag, + }; + + static override contextDefinition = { + ...this.ContextOptions.DynamicProjectConfig, + ...this.ContextOptions.ProjectDir, + ...this.ContextOptions.Vcs, + ...this.ContextOptions.LoggedIn, + }; + + async runAsync(): Promise { + const { flags, args } = await this.parse(WorkflowRun); + + Log.warn('Workflows are in beta and subject to breaking changes.'); + + const { + getDynamicPrivateProjectConfigAsync, + loggedIn: { graphqlClient }, + vcsClient, + projectDir, + } = await this.getContextAsync(WorkflowRun, { + nonInteractive: flags['non-interactive'], + withServerSideEnvironment: null, + }); + + let yamlConfig: string; + try { + yamlConfig = await fs.promises.readFile(path.join(projectDir, args.file), 'utf8'); + } catch (err) { + Log.error('Failed to read workflow file.'); + + throw err; + } + + const { + projectId, + exp: { slug: projectName }, + } = await getDynamicPrivateProjectConfigAsync(); + const account = await getOwnerAccountForProjectIdAsync(graphqlClient, projectId); + + let projectArchiveBucketKey: string; + let easJsonBucketKey: string; + + try { + ({ projectArchiveBucketKey } = await uploadAccountScopedProjectSourceAsync({ + graphqlClient, + vcsClient, + accountId: account.id, + })); + ({ easJsonBucketKey } = await uploadAccountScopedEasJsonAsync({ + graphqlClient, + accountId: account.id, + projectDir, + })); + } catch (err) { + Log.error('Failed to upload project sources.'); + + throw err; + } + + try { + const { id: workflowRunId } = await WorkflowRunMutation.createWorkflowRunAsync( + graphqlClient, + { + appId: projectId, + workflowRevisionInput: { + fileName: path.basename(args.file), + yamlConfig, + }, + workflowRunInput: { + projectSource: { + type: WorkflowProjectSourceType.Gcs, + projectArchiveBucketKey, + easJsonBucketKey, + }, + }, + } + ); + + Log.newLine(); + Log.succeed( + `Workflow started successfully. ${link( + getWorkflowRunUrl(account.name, projectName, workflowRunId) + )}` + ); + } catch (err) { + Log.error('Failed to start the workflow with the API.'); + + throw err; + } + } +} diff --git a/packages/eas-cli/src/graphql/generated.ts b/packages/eas-cli/src/graphql/generated.ts index f992ac45d1..00141d6374 100644 --- a/packages/eas-cli/src/graphql/generated.ts +++ b/packages/eas-cli/src/graphql/generated.ts @@ -710,6 +710,10 @@ export type AccountSsoConfigurationPublicDataQueryPublicDataByAccountNameArgs = accountName: Scalars['String']['input']; }; +export enum AccountUploadSessionType { + WorkflowsProjectSources = 'WORKFLOWS_PROJECT_SOURCES' +} + export type AccountUsageEasBuildMetadata = { __typename?: 'AccountUsageEASBuildMetadata'; billingResourceClass?: Maybe; @@ -1374,6 +1378,7 @@ export type App = Project & { workerDeploymentsCrashes?: Maybe; workerDeploymentsRequest: WorkerDeploymentRequestEdge; workerDeploymentsRequests?: Maybe; + workflowRunsPaginated: AppWorkflowRunsConnection; workflows: Array; }; @@ -1383,7 +1388,6 @@ export type AppActivityTimelineProjectActivitiesArgs = { createdBefore?: InputMaybe; filterChannels?: InputMaybe>; filterPlatforms?: InputMaybe>; - filterReleaseChannels?: InputMaybe>; filterTypes?: InputMaybe>; limit: Scalars['Int']['input']; }; @@ -1647,6 +1651,15 @@ export type AppWorkerDeploymentsRequestsArgs = { timespan: DatasetTimespan; }; + +/** Represents an Exponent App (or Experience in legacy terms) */ +export type AppWorkflowRunsPaginatedArgs = { + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; +}; + export type AppBranchEdge = { __typename?: 'AppBranchEdge'; cursor: Scalars['String']['output']; @@ -2088,6 +2101,18 @@ export type AppWithGithubRepositoryInput = { projectName: Scalars['String']['input']; }; +export type AppWorkflowRunEdge = { + __typename?: 'AppWorkflowRunEdge'; + cursor: Scalars['String']['output']; + node: WorkflowRun; +}; + +export type AppWorkflowRunsConnection = { + __typename?: 'AppWorkflowRunsConnection'; + edges: Array; + pageInfo: PageInfo; +}; + export type AppleAppIdentifier = { __typename?: 'AppleAppIdentifier'; account: Account; @@ -2490,7 +2515,8 @@ export type AuditLog = { metadata?: Maybe; targetEntityId: Scalars['ID']['output']; targetEntityMutationType: TargetEntityMutationType; - targetEntityTypeName: Scalars['String']['output']; + targetEntityTypeName: EntityTypeName; + targetEntityTypePublicName: Scalars['String']['output']; websiteMessage: Scalars['String']['output']; }; @@ -2535,6 +2561,7 @@ export type AuditLogQuery = { __typename?: 'AuditLogQuery'; /** Audit logs for account */ byId: AuditLog; + typeNamesMap: Array; }; @@ -2884,6 +2911,7 @@ export type BuildMetadataInput = { developmentClient?: InputMaybe; distribution?: InputMaybe; environment?: InputMaybe; + fingerprintHash?: InputMaybe; fingerprintSource?: InputMaybe; gitCommitHash?: InputMaybe; gitCommitMessage?: InputMaybe; @@ -3147,7 +3175,9 @@ export enum BuildResourceClass { IosMedium = 'IOS_MEDIUM', IosMLarge = 'IOS_M_LARGE', IosMMedium = 'IOS_M_MEDIUM', - Legacy = 'LEGACY' + Legacy = 'LEGACY', + LinuxLarge = 'LINUX_LARGE', + LinuxMedium = 'LINUX_MEDIUM' } export enum BuildRetryDisabledReason { @@ -3298,8 +3328,8 @@ export type CreateEnvironmentSecretInput = { }; export type CreateEnvironmentVariableInput = { - environment?: InputMaybe; environments?: InputMaybe>; + fileName?: InputMaybe; name: Scalars['String']['input']; overwrite?: InputMaybe; type?: InputMaybe; @@ -3366,6 +3396,8 @@ export type CreateServerlessFunctionUploadUrlResult = { export type CreateSharedEnvironmentVariableInput = { environments?: InputMaybe>; + fileName?: InputMaybe; + isGlobal?: InputMaybe; name: Scalars['String']['input']; overwrite?: InputMaybe; type?: InputMaybe; @@ -3381,8 +3413,8 @@ export type CreateSubmissionResult = { export type CumulativeMetrics = { __typename?: 'CumulativeMetrics'; - /** Totals from the beginning of time till now */ - totals: CumulativeMetricsTotals; + data: UpdatesMetricsData; + metricsAtLastTimestamp: CumulativeMetricsTotals; }; export type CumulativeMetricsOverTimeData = { @@ -3397,6 +3429,14 @@ export type CumulativeMetricsTotals = { totalInstalls: Scalars['Int']['output']; }; +export type CumulativeUpdatesDataset = { + __typename?: 'CumulativeUpdatesDataset'; + cumulative: Array; + difference: Array; + id: Scalars['String']['output']; + label: Scalars['String']['output']; +}; + export type CustomBuildConfigInput = { path: Scalars['String']['input']; }; @@ -3863,25 +3903,25 @@ export type EmailSubscriptionMutationAddUserArgs = { }; export enum EntityTypeName { - Account = 'Account', - AccountSsoConfiguration = 'AccountSSOConfiguration', - AndroidAppCredentials = 'AndroidAppCredentials', - AndroidKeystore = 'AndroidKeystore', - App = 'App', - AppStoreConnectApiKey = 'AppStoreConnectApiKey', - AppleDevice = 'AppleDevice', - AppleDistributionCertificate = 'AppleDistributionCertificate', - AppleProvisioningProfile = 'AppleProvisioningProfile', - AppleTeam = 'AppleTeam', - Branch = 'Branch', - Channel = 'Channel', - Customer = 'Customer', - GoogleServiceAccountKey = 'GoogleServiceAccountKey', - IosAppCredentials = 'IosAppCredentials', - UserInvitation = 'UserInvitation', - UserPermission = 'UserPermission', - Workflow = 'Workflow', - WorkflowRevision = 'WorkflowRevision' + AccountEntity = 'AccountEntity', + AccountSsoConfigurationEntity = 'AccountSSOConfigurationEntity', + AndroidAppCredentialsEntity = 'AndroidAppCredentialsEntity', + AndroidKeystoreEntity = 'AndroidKeystoreEntity', + AppEntity = 'AppEntity', + AppStoreConnectApiKeyEntity = 'AppStoreConnectApiKeyEntity', + AppleDeviceEntity = 'AppleDeviceEntity', + AppleDistributionCertificateEntity = 'AppleDistributionCertificateEntity', + AppleProvisioningProfileEntity = 'AppleProvisioningProfileEntity', + AppleTeamEntity = 'AppleTeamEntity', + BranchEntity = 'BranchEntity', + ChannelEntity = 'ChannelEntity', + CustomerEntity = 'CustomerEntity', + GoogleServiceAccountKeyEntity = 'GoogleServiceAccountKeyEntity', + IosAppCredentialsEntity = 'IosAppCredentialsEntity', + UserInvitationEntity = 'UserInvitationEntity', + UserPermissionEntity = 'UserPermissionEntity', + WorkflowEntity = 'WorkflowEntity', + WorkflowRevisionEntity = 'WorkflowRevisionEntity' } export type EnvironmentSecret = { @@ -3929,9 +3969,10 @@ export type EnvironmentVariable = { __typename?: 'EnvironmentVariable'; apps: Array; createdAt: Scalars['DateTime']['output']; - environment?: Maybe; environments?: Maybe>; + fileName?: Maybe; id: Scalars['ID']['output']; + isGlobal?: Maybe; linkedEnvironments?: Maybe>; name: Scalars['String']['output']; scope: EnvironmentVariableScope; @@ -4048,9 +4089,10 @@ export type EnvironmentVariableWithSecret = { __typename?: 'EnvironmentVariableWithSecret'; apps: Array; createdAt: Scalars['DateTime']['output']; - environment?: Maybe; environments?: Maybe>; + fileName?: Maybe; id: Scalars['ID']['output']; + isGlobal: Scalars['Boolean']['output']; linkedEnvironments?: Maybe>; name: Scalars['String']['output']; scope: EnvironmentVariableScope; @@ -5034,6 +5076,12 @@ export type LinkSharedEnvironmentVariableInput = { environmentVariableId: Scalars['ID']['input']; }; +export type LogNameTypeMapping = { + __typename?: 'LogNameTypeMapping'; + publicName: Scalars['String']['output']; + typeName: EntityTypeName; +}; + export type LogsTimespan = { end: Scalars['DateTime']['input']; start?: InputMaybe; @@ -5041,7 +5089,9 @@ export type LogsTimespan = { export enum MailchimpAudience { ExpoDevelopers = 'EXPO_DEVELOPERS', - ExpoDeveloperOnboarding = 'EXPO_DEVELOPER_ONBOARDING' + ExpoDeveloperOnboarding = 'EXPO_DEVELOPER_ONBOARDING', + LaunchParty_2024 = 'LAUNCH_PARTY_2024', + NonprodExpoDevelopers = 'NONPROD_EXPO_DEVELOPERS' } export enum MailchimpTag { @@ -5689,6 +5739,7 @@ export type RootMutation = { /** Mutations that modify a websiteNotification */ websiteNotifications: WebsiteNotificationMutation; workflowJob: WorkflowJobMutation; + workflowRun: WorkflowRunMutation; }; @@ -5818,7 +5869,9 @@ export type RootQuery = { /** Top-level query object for querying Webhooks. */ webhook: WebhookQuery; workerDeployment: WorkerDeploymentQuery; + workflowJobs: WorkflowJobQuery; workflowRevisions: WorkflowRevisionQuery; + workflowRuns: WorkflowRunQuery; workflows: WorkflowQuery; }; @@ -6112,6 +6165,8 @@ export type Snack = Project & { /** Preview image of the running snack */ previewImage?: Maybe; published: Scalars['Boolean']['output']; + /** SDK version of the snack */ + sdkVersion: Scalars['String']['output']; /** Slug name, e.g. "mysnack", "245631" */ slug: Scalars['String']['output']; /** Date and time the Snack was last updated */ @@ -6666,7 +6721,9 @@ export type UpdateDeploymentsConnection = { export type UpdateEnvironmentVariableInput = { environments?: InputMaybe>; + fileName?: InputMaybe; id: Scalars['ID']['input']; + isGlobal?: InputMaybe; name?: InputMaybe; type?: InputMaybe; value?: InputMaybe; @@ -6705,13 +6762,12 @@ export type UpdateInfoGroup = { export type UpdateInsights = { __typename?: 'UpdateInsights'; cumulativeMetrics: CumulativeMetrics; - cumulativeMetricsOverTime: CumulativeMetricsOverTimeData; id: Scalars['ID']['output']; totalUniqueUsers: Scalars['Int']['output']; }; -export type UpdateInsightsCumulativeMetricsOverTimeArgs = { +export type UpdateInsightsCumulativeMetricsArgs = { timespan: InsightsTimespan; }; @@ -6781,13 +6837,28 @@ export type UpdatesFilter = { sdkVersions?: InputMaybe>; }; +export type UpdatesMetricsData = { + __typename?: 'UpdatesMetricsData'; + failedInstallsDataset: CumulativeUpdatesDataset; + installsDataset: CumulativeUpdatesDataset; + labels: Array; +}; + export type UploadSession = { __typename?: 'UploadSession'; + /** Create an Upload Session for a specific account */ + createAccountScopedUploadSession: Scalars['JSONObject']['output']; /** Create an Upload Session */ createUploadSession: Scalars['JSONObject']['output']; }; +export type UploadSessionCreateAccountScopedUploadSessionArgs = { + accountID: Scalars['ID']['input']; + type: AccountUploadSessionType; +}; + + export type UploadSessionCreateUploadSessionArgs = { type: UploadSessionType; }; @@ -7152,7 +7223,8 @@ export type UserAuditLog = { metadata?: Maybe; targetEntityId: Scalars['ID']['output']; targetEntityMutationType: TargetEntityMutationType; - targetEntityTypeName: Scalars['String']['output']; + targetEntityTypeName: UserEntityTypeName; + targetEntityTypePublicName: Scalars['String']['output']; user: User; websiteMessage: Scalars['String']['output']; }; @@ -7199,6 +7271,7 @@ export type UserAuditLogQuery = { /** Audit logs for user */ byId: UserAuditLog; byUserIdPaginated: UserAuditLogConnection; + typeNamesMap: Array; }; @@ -7227,15 +7300,15 @@ export type UserDataInput = { }; export enum UserEntityTypeName { - AccessToken = 'AccessToken', - DiscordUser = 'DiscordUser', - GitHubUser = 'GitHubUser', - Password = 'Password', - SsoUser = 'SSOUser', - User = 'User', - UserPermission = 'UserPermission', - UserSecondFactorBackupCodes = 'UserSecondFactorBackupCodes', - UserSecondFactorDevice = 'UserSecondFactorDevice' + AccessTokenEntity = 'AccessTokenEntity', + DiscordUserEntity = 'DiscordUserEntity', + GitHubUserEntity = 'GitHubUserEntity', + PasswordEntity = 'PasswordEntity', + SsoUserEntity = 'SSOUserEntity', + UserEntity = 'UserEntity', + UserPermissionEntity = 'UserPermissionEntity', + UserSecondFactorBackupCodesEntity = 'UserSecondFactorBackupCodesEntity', + UserSecondFactorDeviceEntity = 'UserSecondFactorDeviceEntity' } /** An pending invitation sent to an email granting membership on an Account. */ @@ -7339,6 +7412,12 @@ export type UserInvitationPublicDataQueryByTokenArgs = { token: Scalars['ID']['input']; }; +export type UserLogNameTypeMapping = { + __typename?: 'UserLogNameTypeMapping'; + publicName: Scalars['String']['output']; + typeName: UserEntityTypeName; +}; + export type UserPermission = { __typename?: 'UserPermission'; actor: Actor; @@ -7633,7 +7712,7 @@ export type WorkerDeploymentCrashesAggregationNode = { distinctCrashes: Scalars['Int']['output']; firstOccurredAt: Scalars['DateTime']['output']; mostRecentlyOccurredAt: Scalars['DateTime']['output']; - sampleRate: Scalars['Float']['output']; + sampleRate?: Maybe; }; export type WorkerDeploymentCrashesHashEdge = { @@ -7827,7 +7906,7 @@ export type WorkerDeploymentRequestsAggregationNode = { durationP99: Scalars['Float']['output']; requestsPerMs?: Maybe; requestsSum: Scalars['Int']['output']; - sampleRate: Scalars['Float']['output']; + sampleRate?: Maybe; serverErrorRatio: Scalars['Float']['output']; serverErrorRatioP50: Scalars['Float']['output']; serverErrorRatioP90: Scalars['Float']['output']; @@ -7922,10 +8001,52 @@ export type Workflow = { fileName: Scalars['String']['output']; id: Scalars['ID']['output']; name?: Maybe; - revisions: Array; + revisionsPaginated: WorkflowRevisionsConnection; + runsPaginated: WorkflowRunsConnection; updatedAt: Scalars['DateTime']['output']; }; + +export type WorkflowRevisionsPaginatedArgs = { + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; +}; + + +export type WorkflowRunsPaginatedArgs = { + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; +}; + +export type WorkflowJob = { + __typename?: 'WorkflowJob'; + createdAt: Scalars['DateTime']['output']; + credentialsAppleDeviceRegistrationRequest?: Maybe; + errors: Array; + id: Scalars['ID']['output']; + key: Scalars['String']['output']; + name: Scalars['String']['output']; + outputs: Scalars['JSONObject']['output']; + requiredJobKeys: Array; + status: WorkflowJobStatus; + turtleBuild?: Maybe; + turtleJobRun?: Maybe; + turtleSubmission?: Maybe; + type: WorkflowJobType; + updatedAt: Scalars['DateTime']['output']; + workflowRun: WorkflowRun; +}; + +export type WorkflowJobError = { + __typename?: 'WorkflowJobError'; + message: Scalars['String']['output']; + title: Scalars['String']['output']; +}; + export type WorkflowJobMutation = { __typename?: 'WorkflowJobMutation'; approveWorkflowJob: Scalars['ID']['output']; @@ -7936,6 +8057,46 @@ export type WorkflowJobMutationApproveWorkflowJobArgs = { workflowJobId: Scalars['ID']['input']; }; +export type WorkflowJobQuery = { + __typename?: 'WorkflowJobQuery'; + byId: WorkflowJob; +}; + + +export type WorkflowJobQueryByIdArgs = { + workflowJobId: Scalars['ID']['input']; +}; + +export enum WorkflowJobStatus { + ActionRequired = 'ACTION_REQUIRED', + Canceled = 'CANCELED', + Failure = 'FAILURE', + InProgress = 'IN_PROGRESS', + New = 'NEW', + Skipped = 'SKIPPED', + Success = 'SUCCESS' +} + +export enum WorkflowJobType { + AppleDeviceRegistrationRequest = 'APPLE_DEVICE_REGISTRATION_REQUEST', + Build = 'BUILD', + Custom = 'CUSTOM', + MaestroTest = 'MAESTRO_TEST', + RequireApproval = 'REQUIRE_APPROVAL', + Submission = 'SUBMISSION', + Update = 'UPDATE' +} + +export type WorkflowProjectSourceInput = { + easJsonBucketKey: Scalars['String']['input']; + projectArchiveBucketKey: Scalars['String']['input']; + type: WorkflowProjectSourceType; +}; + +export enum WorkflowProjectSourceType { + Gcs = 'GCS' +} + /** Look up Workflow by ID */ export type WorkflowQuery = { __typename?: 'WorkflowQuery'; @@ -7951,13 +8112,24 @@ export type WorkflowQueryByIdArgs = { export type WorkflowRevision = { __typename?: 'WorkflowRevision'; blobSha: Scalars['String']['output']; - commitSha: Scalars['String']['output']; + commitSha?: Maybe; createdAt: Scalars['DateTime']['output']; id: Scalars['ID']['output']; workflow: Workflow; yamlConfig: Scalars['String']['output']; }; +export type WorkflowRevisionEdge = { + __typename?: 'WorkflowRevisionEdge'; + cursor: Scalars['String']['output']; + node: WorkflowRevision; +}; + +export type WorkflowRevisionInput = { + fileName: Scalars['String']['input']; + yamlConfig: Scalars['String']['input']; +}; + export type WorkflowRevisionQuery = { __typename?: 'WorkflowRevisionQuery'; byId: WorkflowRevision; @@ -7968,6 +8140,77 @@ export type WorkflowRevisionQueryByIdArgs = { workflowRevisionId: Scalars['ID']['input']; }; +export type WorkflowRevisionsConnection = { + __typename?: 'WorkflowRevisionsConnection'; + edges: Array; + pageInfo: PageInfo; +}; + +export type WorkflowRun = { + __typename?: 'WorkflowRun'; + createdAt: Scalars['DateTime']['output']; + gitCommitHash?: Maybe; + gitCommitMessage?: Maybe; + githubRepository?: Maybe; + id: Scalars['ID']['output']; + initiatingUser?: Maybe; + jobs: Array; + name: Scalars['String']['output']; + pullRequestNumber?: Maybe; + requestedGitRef?: Maybe; + status: WorkflowRunStatus; + updatedAt: Scalars['DateTime']['output']; + workflow: Workflow; + workflowRevision?: Maybe; +}; + +export type WorkflowRunEdge = { + __typename?: 'WorkflowRunEdge'; + cursor: Scalars['String']['output']; + node: WorkflowRun; +}; + +export type WorkflowRunInput = { + projectSource: WorkflowProjectSourceInput; +}; + +export type WorkflowRunMutation = { + __typename?: 'WorkflowRunMutation'; + createWorkflowRun: WorkflowRun; +}; + + +export type WorkflowRunMutationCreateWorkflowRunArgs = { + appId: Scalars['ID']['input']; + workflowRevisionInput: WorkflowRevisionInput; + workflowRunInput: WorkflowRunInput; +}; + +export type WorkflowRunQuery = { + __typename?: 'WorkflowRunQuery'; + byId: WorkflowRun; +}; + + +export type WorkflowRunQueryByIdArgs = { + workflowRunId: Scalars['ID']['input']; +}; + +export enum WorkflowRunStatus { + ActionRequired = 'ACTION_REQUIRED', + Canceled = 'CANCELED', + Failure = 'FAILURE', + InProgress = 'IN_PROGRESS', + New = 'NEW', + Success = 'SUCCESS' +} + +export type WorkflowRunsConnection = { + __typename?: 'WorkflowRunsConnection'; + edges: Array; + pageInfo: PageInfo; +}; + export type DeleteAndroidAppBuildCredentialsResult = { __typename?: 'deleteAndroidAppBuildCredentialsResult'; id: Scalars['ID']['output']; @@ -8686,6 +8929,14 @@ export type CreateUploadSessionMutationVariables = Exact<{ export type CreateUploadSessionMutation = { __typename?: 'RootMutation', uploadSession: { __typename?: 'UploadSession', createUploadSession: any } }; +export type CreateAccountScopedUploadSessionMutationVariables = Exact<{ + accountID: Scalars['ID']['input']; + type: AccountUploadSessionType; +}>; + + +export type CreateAccountScopedUploadSessionMutation = { __typename?: 'RootMutation', uploadSession: { __typename?: 'UploadSession', createAccountScopedUploadSession: any } }; + export type MarkCliDoneInOnboardingUserPreferencesMutationVariables = Exact<{ preferences: UserPreferencesInput; }>; @@ -8716,6 +8967,15 @@ export type DeleteWebhookMutationVariables = Exact<{ export type DeleteWebhookMutation = { __typename?: 'RootMutation', webhook: { __typename?: 'WebhookMutation', deleteWebhook: { __typename?: 'DeleteWebhookResult', id: string } } }; +export type CreateWorkflowRunMutationVariables = Exact<{ + appId: Scalars['ID']['input']; + workflowRevisionInput: WorkflowRevisionInput; + workflowRunInput: WorkflowRunInput; +}>; + + +export type CreateWorkflowRunMutation = { __typename?: 'RootMutation', workflowRun: { __typename?: 'WorkflowRunMutation', createWorkflowRun: { __typename?: 'WorkflowRun', id: string } } }; + export type AppByIdQueryVariables = Exact<{ appId: Scalars['String']['input']; }>; @@ -8862,7 +9122,7 @@ export type EnvironmentVariablesIncludingSensitiveByAppIdQueryVariables = Exact< }>; -export type EnvironmentVariablesIncludingSensitiveByAppIdQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, environmentVariablesIncludingSensitive: Array<{ __typename?: 'EnvironmentVariableWithSecret', id: string, name: string, value?: string | null, environments?: Array | null, valueWithFileContent?: string | null }> } } }; +export type EnvironmentVariablesIncludingSensitiveByAppIdQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, environmentVariablesIncludingSensitive: Array<{ __typename?: 'EnvironmentVariableWithSecret', id: string, name: string, value?: string | null, environments?: Array | null, createdAt: any, updatedAt: any, scope: EnvironmentVariableScope, visibility: EnvironmentVariableVisibility, type: EnvironmentSecretType, valueWithFileContent?: string | null }> } } }; export type EnvironmentVariablesByAppIdQueryVariables = Exact<{ appId: Scalars['String']['input']; @@ -8892,7 +9152,7 @@ export type EnvironmentVariablesSharedWithSensitiveQueryVariables = Exact<{ }>; -export type EnvironmentVariablesSharedWithSensitiveQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, ownerAccount: { __typename?: 'Account', id: string, environmentVariablesIncludingSensitive: Array<{ __typename?: 'EnvironmentVariableWithSecret', id: string, name: string, value?: string | null, environments?: Array | null, valueWithFileContent?: string | null }> } } } }; +export type EnvironmentVariablesSharedWithSensitiveQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, ownerAccount: { __typename?: 'Account', id: string, environmentVariablesIncludingSensitive: Array<{ __typename?: 'EnvironmentVariableWithSecret', id: string, name: string, value?: string | null, environments?: Array | null, createdAt: any, updatedAt: any, scope: EnvironmentVariableScope, visibility: EnvironmentVariableVisibility, type: EnvironmentSecretType, valueWithFileContent?: string | null }> } } } }; export type GoogleServiceAccountKeyByIdQueryVariables = Exact<{ ascApiKeyId: Scalars['ID']['input']; @@ -9013,6 +9273,8 @@ export type EnvironmentSecretFragment = { __typename?: 'EnvironmentSecret', id: export type EnvironmentVariableFragment = { __typename?: 'EnvironmentVariable', id: string, name: string, value?: string | null, environments?: Array | null, createdAt: any, updatedAt: any, scope: EnvironmentVariableScope, visibility?: EnvironmentVariableVisibility | null, type: EnvironmentSecretType }; +export type EnvironmentVariableWithSecretFragment = { __typename?: 'EnvironmentVariableWithSecret', id: string, name: string, value?: string | null, environments?: Array | null, createdAt: any, updatedAt: any, scope: EnvironmentVariableScope, visibility: EnvironmentVariableVisibility, type: EnvironmentSecretType }; + export type RuntimeFragment = { __typename?: 'Runtime', id: string, version: string }; export type StatuspageServiceFragment = { __typename?: 'StatuspageService', id: string, name: StatuspageServiceName, status: StatuspageServiceStatus, incidents: Array<{ __typename?: 'StatuspageIncident', id: string, status: StatuspageIncidentStatus, name: string, impact: StatuspageIncidentImpact, shortlink: string }> }; diff --git a/packages/eas-cli/src/graphql/mutations/UploadSessionMutation.ts b/packages/eas-cli/src/graphql/mutations/UploadSessionMutation.ts index 3f21aa4861..f5703e3f24 100644 --- a/packages/eas-cli/src/graphql/mutations/UploadSessionMutation.ts +++ b/packages/eas-cli/src/graphql/mutations/UploadSessionMutation.ts @@ -3,6 +3,9 @@ import gql from 'graphql-tag'; import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient'; import { withErrorHandlingAsync } from '../client'; import { + AccountUploadSessionType, + CreateAccountScopedUploadSessionMutation, + CreateAccountScopedUploadSessionMutationVariables, CreateUploadSessionMutation, CreateUploadSessionMutationVariables, UploadSessionType, @@ -37,4 +40,39 @@ export const UploadSessionMutation = { ); return data.uploadSession.createUploadSession; }, + async createAccountScopedUploadSessionAsync( + graphqlClient: ExpoGraphqlClient, + { + type, + accountID, + }: { + type: AccountUploadSessionType; + accountID: string; + } + ): Promise { + const data = await withErrorHandlingAsync( + graphqlClient + .mutation< + CreateAccountScopedUploadSessionMutation, + CreateAccountScopedUploadSessionMutationVariables + >( + gql` + mutation CreateAccountScopedUploadSessionMutation( + $accountID: ID! + $type: AccountUploadSessionType! + ) { + uploadSession { + createAccountScopedUploadSession(accountID: $accountID, type: $type) + } + } + `, + { + type, + accountID, + } + ) + .toPromise() + ); + return data.uploadSession.createAccountScopedUploadSession; + }, }; diff --git a/packages/eas-cli/src/graphql/mutations/WorkflowRunMutation.ts b/packages/eas-cli/src/graphql/mutations/WorkflowRunMutation.ts new file mode 100644 index 0000000000..e004c89124 --- /dev/null +++ b/packages/eas-cli/src/graphql/mutations/WorkflowRunMutation.ts @@ -0,0 +1,55 @@ +import gql from 'graphql-tag'; + +import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient'; +import { withErrorHandlingAsync } from '../client'; +import { + CreateWorkflowRunMutation, + CreateWorkflowRunMutationVariables, + WorkflowRevisionInput, + WorkflowRunInput, +} from '../generated'; + +export namespace WorkflowRunMutation { + export async function createWorkflowRunAsync( + graphqlClient: ExpoGraphqlClient, + { + appId, + workflowRevisionInput, + workflowRunInput, + }: { + appId: string; + workflowRevisionInput: WorkflowRevisionInput; + workflowRunInput: WorkflowRunInput; + } + ): Promise<{ id: string }> { + const data = await withErrorHandlingAsync( + graphqlClient + .mutation( + gql` + mutation CreateWorkflowRun( + $appId: ID! + $workflowRevisionInput: WorkflowRevisionInput! + $workflowRunInput: WorkflowRunInput! + ) { + workflowRun { + createWorkflowRun( + appId: $appId + workflowRevisionInput: $workflowRevisionInput + workflowRunInput: $workflowRunInput + ) { + id + } + } + } + `, + { + appId, + workflowRevisionInput, + workflowRunInput, + } + ) + .toPromise() + ); + return { id: data.workflowRun.createWorkflowRun.id }; + } +} diff --git a/packages/eas-cli/src/project/uploadAccountScopedEasJsonAsync.ts b/packages/eas-cli/src/project/uploadAccountScopedEasJsonAsync.ts new file mode 100644 index 0000000000..4770ea918b --- /dev/null +++ b/packages/eas-cli/src/project/uploadAccountScopedEasJsonAsync.ts @@ -0,0 +1,47 @@ +import chalk from 'chalk'; +import fs from 'node:fs'; +import path from 'node:path'; + +import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient'; +import { AccountUploadSessionType } from '../graphql/generated'; +import { uploadAccountScopedFileAtPathToGCSAsync } from '../uploads'; +import { formatBytes } from '../utils/files'; +import { createProgressTracker } from '../utils/progress'; + +/** + * Uploads the `eas.json` file to GCS as account-scoped object. + * Used in workflows. Takes care of logging progress. + */ +export async function uploadAccountScopedEasJsonAsync({ + graphqlClient, + accountId, + projectDir, +}: { + graphqlClient: ExpoGraphqlClient; + accountId: string; + projectDir: string; +}): Promise<{ easJsonBucketKey: string }> { + const easJsonFilePath = path.join(projectDir, 'eas.json'); + + const easJsonFileStat = await fs.promises.stat(easJsonFilePath); + + if (easJsonFileStat.size > 1024 * 1024) { + throw new Error('eas.json is too big. Maximum allowed size is 1MB.'); + } + + const easJsonBucketKey = await uploadAccountScopedFileAtPathToGCSAsync(graphqlClient, { + accountId, + type: AccountUploadSessionType.WorkflowsProjectSources, + path: easJsonFilePath, + handleProgressEvent: createProgressTracker({ + total: easJsonFileStat.size, + message: ratio => + `Uploading eas.json to EAS (${formatBytes(easJsonFileStat.size * ratio)} / ${formatBytes( + easJsonFileStat.size + )})`, + completedMessage: (duration: string) => `Uploaded eas.json to EAS ${chalk.dim(duration)}`, + }), + }); + + return { easJsonBucketKey }; +} diff --git a/packages/eas-cli/src/project/uploadAccountScopedProjectSourceAsync.ts b/packages/eas-cli/src/project/uploadAccountScopedProjectSourceAsync.ts new file mode 100644 index 0000000000..c218438902 --- /dev/null +++ b/packages/eas-cli/src/project/uploadAccountScopedProjectSourceAsync.ts @@ -0,0 +1,74 @@ +import chalk from 'chalk'; +import fs from 'node:fs'; + +import { makeProjectTarballAsync } from '../build/utils/repository'; +import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient'; +import { AccountUploadSessionType } from '../graphql/generated'; +import Log, { learnMore } from '../log'; +import { uploadAccountScopedFileAtPathToGCSAsync } from '../uploads'; +import { formatBytes } from '../utils/files'; +import { createProgressTracker } from '../utils/progress'; +import { Client } from '../vcs/vcs'; + +/** + * Archives the project and uploads it to GCS as account-scoped object. + * Used in workflows. Takes care of logging progress and cleaning up the tarball. + */ +export async function uploadAccountScopedProjectSourceAsync({ + graphqlClient, + vcsClient, + accountId, +}: { + graphqlClient: ExpoGraphqlClient; + vcsClient: Client; + accountId: string; +}): Promise<{ projectArchiveBucketKey: string }> { + let projectTarballPath; + + try { + Log.newLine(); + Log.log( + `Compressing project files and uploading to EAS. ${learnMore( + 'https://expo.fyi/eas-build-archive' + )}` + ); + + const projectTarball = await makeProjectTarballAsync(vcsClient); + projectTarballPath = projectTarball.path; + + if (projectTarball.size > 1024 * 1024 * 100) { + Log.warn( + `Your project archive is ${formatBytes( + projectTarball.size + )}. You can reduce its size and the time it takes to upload by excluding files that are unnecessary for the build process in ${chalk.bold( + '.easignore' + )} file. ${learnMore('https://expo.fyi/eas-build-archive')}` + ); + } + + if (projectTarball.size > 2 * 1024 * 1024 * 1024) { + throw new Error('Project archive is too big. Maximum allowed size is 2GB.'); + } + + const projectArchiveBucketKey = await uploadAccountScopedFileAtPathToGCSAsync(graphqlClient, { + accountId, + type: AccountUploadSessionType.WorkflowsProjectSources, + path: projectTarball.path, + handleProgressEvent: createProgressTracker({ + total: projectTarball.size, + message: ratio => + `Uploading project archive to EAS (${formatBytes( + projectTarball.size * ratio + )} / ${formatBytes(projectTarball.size)})`, + completedMessage: (duration: string) => + `Uploaded project archive to EAS ${chalk.dim(duration)}`, + }), + }); + + return { projectArchiveBucketKey }; + } finally { + if (projectTarballPath) { + await fs.promises.rm(projectTarballPath); + } + } +} diff --git a/packages/eas-cli/src/uploads.ts b/packages/eas-cli/src/uploads.ts index 051263424c..e4427b696e 100644 --- a/packages/eas-cli/src/uploads.ts +++ b/packages/eas-cli/src/uploads.ts @@ -5,7 +5,7 @@ import promiseRetry from 'promise-retry'; import { ExpoGraphqlClient } from './commandUtils/context/contextUtils/createGraphqlClient'; import fetch from './fetch'; -import { UploadSessionType } from './graphql/generated'; +import { AccountUploadSessionType, UploadSessionType } from './graphql/generated'; import { SignedUrl, UploadSessionMutation } from './graphql/mutations/UploadSessionMutation'; import { ProgressHandler } from './utils/progress'; @@ -26,6 +26,29 @@ export async function uploadFileAtPathToGCSAsync( return signedUrl.bucketKey; } +export async function uploadAccountScopedFileAtPathToGCSAsync( + graphqlClient: ExpoGraphqlClient, + { + type, + accountId, + path, + handleProgressEvent, + }: { + type: AccountUploadSessionType; + accountId: string; + path: string; + handleProgressEvent: ProgressHandler; + } +): Promise { + const signedUrl = await UploadSessionMutation.createAccountScopedUploadSessionAsync( + graphqlClient, + { type, accountID: accountId } + ); + + await uploadWithSignedUrlWithProgressAsync(path, signedUrl, handleProgressEvent); + return signedUrl.bucketKey; +} + export async function uploadWithPresignedPostWithRetryAsync( file: string, presignedPost: PresignedPost, diff --git a/packages/eas-cli/src/utils/progress.ts b/packages/eas-cli/src/utils/progress.ts index aa87e0d9f2..f56c2144e9 100644 --- a/packages/eas-cli/src/utils/progress.ts +++ b/packages/eas-cli/src/utils/progress.ts @@ -1,4 +1,5 @@ import chalk from 'chalk'; +import { randomUUID } from 'node:crypto'; import { endTimer, formatMilliseconds, startTimer } from './timer'; import { Ora, ora } from '../ora'; @@ -29,7 +30,7 @@ export function createProgressTracker({ let transferredSoFar = 0; let current = 0; - const timerLabel = String(Date.now()); + const timerLabel = String(randomUUID()); const getMessage = (v: number, total: number): string => { const ratio = Math.min(Math.max(v, 0), 1);