-
Notifications
You must be signed in to change notification settings - Fork 1.4k
[wrangler] Add PR metadata to preview deployments #14966
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| import path from "node:path"; | ||
| import { | ||
| APIError, | ||
| configFileName, | ||
| getBindingTypeFriendlyName, | ||
| UserError, | ||
|
|
@@ -27,9 +28,12 @@ import { | |
| getBranchName, | ||
| getHeadCommitMessage, | ||
| getHeadCommitRef, | ||
| getPullRequestMetadata, | ||
| getRepositoryUrl, | ||
| resolveWorkerName, | ||
| shouldUseCIMetadataFallback, | ||
| } from "./shared"; | ||
| import type { PullRequestMetadata } from "./shared"; | ||
| import type { WorkerBuildResult } from "../shared/types"; | ||
| import type { | ||
| Binding, | ||
|
|
@@ -81,6 +85,10 @@ type MergedVersionLevel = { | |
| value: Config["cache"]; | ||
| fromConfig: boolean; | ||
| }; | ||
| pull_request?: { | ||
| value: string; | ||
| fromConfig: false; | ||
| }; | ||
| assets?: { | ||
| value: { | ||
| directory?: string; | ||
|
|
@@ -240,6 +248,8 @@ async function assemblePreviewDeploymentSettings( | |
| options: { | ||
| message?: string; | ||
| tag?: string; | ||
| repositoryUrl?: string; | ||
| pullRequest?: PullRequestMetadata; | ||
| assetsOptions?: PreviewAssetsOptions; | ||
| } | ||
| ): Promise<CreatePreviewDeploymentRequestParams> { | ||
|
|
@@ -276,9 +286,16 @@ async function assemblePreviewDeploymentSettings( | |
| if (config.compatibility_flags && config.compatibility_flags.length > 0) { | ||
| request.compatibility_flags = config.compatibility_flags; | ||
| } | ||
| if (options.message || options.tag) { | ||
| const repositoryUrl = options.repositoryUrl; | ||
| const pullRequest = options.pullRequest; | ||
| if (options.message || options.tag || repositoryUrl || pullRequest) { | ||
| request.annotations = { | ||
| ...(options.message && { "workers/message": options.message }), | ||
| ...(pullRequest?.number && { | ||
| "workers/pull_request_number": pullRequest.number, | ||
| }), | ||
| ...(pullRequest?.url && { "workers/pull_request_url": pullRequest.url }), | ||
| ...(repositoryUrl && { "workers/repository_url": repositoryUrl }), | ||
| ...(options.tag && { "workers/tag": options.tag }), | ||
| }; | ||
| } | ||
|
|
@@ -374,7 +391,9 @@ function buildMergedScriptLevel( | |
|
|
||
| function buildMergedVersionLevel( | ||
| config: Config, | ||
| deployment: DeploymentResource | ||
| deployment: DeploymentResource, | ||
| repositoryUrl?: string, | ||
| pullRequest?: PullRequestMetadata | ||
| ): MergedVersionLevel { | ||
| const previews = config.previews as PreviewsConfig | undefined; | ||
| const configBindingNames = new Set( | ||
|
|
@@ -429,6 +448,17 @@ function buildMergedVersionLevel( | |
| fromConfig: previews?.cache !== undefined || config.cache !== undefined, | ||
| }; | ||
| } | ||
| const deploymentPullRequestUrl = | ||
| deployment.annotations?.["workers/pull_request_url"] ?? pullRequest?.url; | ||
| const deploymentPullRequestNumber = | ||
| deployment.annotations?.["workers/pull_request_number"] ?? | ||
| pullRequest?.number; | ||
| if (deploymentPullRequestUrl || deploymentPullRequestNumber) { | ||
| result.pull_request = { | ||
| value: deploymentPullRequestUrl ?? `#${deploymentPullRequestNumber}`, | ||
| fromConfig: false, | ||
| }; | ||
| } | ||
| if (config.assets) { | ||
| result.assets = { | ||
| value: { | ||
|
|
@@ -448,6 +478,81 @@ function buildMergedVersionLevel( | |
| return result; | ||
| } | ||
|
|
||
| function hasPreviewMetadataAnnotations( | ||
| request: CreatePreviewDeploymentRequestParams | ||
| ): boolean { | ||
| return !!( | ||
| request.annotations?.["workers/pull_request_number"] || | ||
| request.annotations?.["workers/pull_request_url"] || | ||
| request.annotations?.["workers/repository_url"] | ||
| ); | ||
| } | ||
|
|
||
| function omitPreviewMetadataAnnotations( | ||
| request: CreatePreviewDeploymentRequestParams | ||
| ): CreatePreviewDeploymentRequestParams { | ||
| const annotations = { | ||
| ...(request.annotations?.["workers/message"] && { | ||
| "workers/message": request.annotations["workers/message"], | ||
| }), | ||
| ...(request.annotations?.["workers/tag"] && { | ||
| "workers/tag": request.annotations["workers/tag"], | ||
| }), | ||
| }; | ||
|
|
||
| return { | ||
| ...request, | ||
| annotations: | ||
| Object.keys(annotations).length > 0 ? annotations : undefined, | ||
| }; | ||
| } | ||
|
|
||
| function isPreviewMetadataAnnotationsUnsupportedError(error: unknown): boolean { | ||
| if (typeof error !== "object" || error === null) { | ||
| return false; | ||
| } | ||
|
|
||
| const code = "code" in error ? error.code : undefined; | ||
| if (code !== undefined && code !== 10021) { | ||
| return false; | ||
| } | ||
|
|
||
| const messages = [ | ||
| error instanceof Error ? error.message : undefined, | ||
| error instanceof APIError ? error.text : undefined, | ||
| ...getErrorNoteTexts(error), | ||
| ] | ||
| .filter(Boolean) | ||
| .join("\n"); | ||
|
|
||
| return ( | ||
| messages.includes("annotations not allowed") && | ||
| (messages.includes("workers/pull_request") || | ||
| messages.includes("workers/repository_url")) | ||
| ); | ||
| } | ||
|
|
||
| function getErrorNoteTexts(error: unknown): string[] { | ||
| if (typeof error !== "object" || error === null || !("notes" in error)) { | ||
| return []; | ||
| } | ||
|
|
||
| const notes = error.notes; | ||
| if (!Array.isArray(notes)) { | ||
| return []; | ||
| } | ||
|
|
||
| return notes.flatMap((note) => [ | ||
| typeof note === "object" && | ||
| note !== null && | ||
| "text" in note && | ||
| typeof note.text === "string" | ||
| ? note.text | ||
| : undefined, | ||
| ...getErrorNoteTexts(note), | ||
| ]).filter((text): text is string => text !== undefined); | ||
| } | ||
|
|
||
| function formatPreviewResource( | ||
| previewResource: PreviewResource, | ||
| scriptLevel: MergedScriptLevel, | ||
|
|
@@ -565,6 +670,13 @@ function formatDeploymentResource( | |
| versionLevel.cache.fromConfig, | ||
| ]); | ||
| } | ||
| if (versionLevel.pull_request !== undefined) { | ||
| settingsRows.push([ | ||
| "pull_request", | ||
| versionLevel.pull_request.value, | ||
| versionLevel.pull_request.fromConfig, | ||
| ]); | ||
| } | ||
| if (settingsRows.length > 0) { | ||
| lines.push(""); | ||
| lines.push(...formatAlignedRows(settingsRows)); | ||
|
|
@@ -682,6 +794,8 @@ export async function preview( | |
| !args.message && shouldUseCIMetadataFallback() | ||
| ? getHeadCommitMessage() | ||
| : undefined; | ||
| const repositoryUrl = getRepositoryUrl(); | ||
| const pullRequest = getPullRequestMetadata(); | ||
|
Comment on lines
+797
to
+798
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Local previews now send repository details even outside CI, unlike other automatically detected metadata The repository address is attached to every preview deployment ( Inconsistency with the existing CI-metadata gatingCommit tag/message fallbacks are guarded by Was this helpful? React with 👍 or 👎 to provide feedback. |
||
|
|
||
| let existingPreview: PreviewResource | null = null; | ||
| try { | ||
|
|
@@ -732,25 +846,51 @@ export async function preview( | |
| { | ||
| message: args.message ?? fallbackMessage, | ||
| tag: args.tag ?? fallbackTag, | ||
| repositoryUrl, | ||
| pullRequest, | ||
| assetsOptions, | ||
| } | ||
| ); | ||
| const deployment = await createPreviewDeployment( | ||
| config, | ||
| accountId, | ||
| workerName, | ||
| previewResource.id, | ||
| deploymentRequest, | ||
| { ignoreDefaults } | ||
| ); | ||
| let deployment: DeploymentResource; | ||
| try { | ||
| deployment = await createPreviewDeployment( | ||
| config, | ||
| accountId, | ||
| workerName, | ||
| previewResource.id, | ||
| deploymentRequest, | ||
| { ignoreDefaults } | ||
| ); | ||
| } catch (error) { | ||
| if ( | ||
| hasPreviewMetadataAnnotations(deploymentRequest) && | ||
| isPreviewMetadataAnnotationsUnsupportedError(error) | ||
| ) { | ||
| deployment = await createPreviewDeployment( | ||
| config, | ||
| accountId, | ||
| workerName, | ||
| previewResource.id, | ||
| omitPreviewMetadataAnnotations(deploymentRequest), | ||
| { ignoreDefaults } | ||
| ); | ||
| } else { | ||
| throw error; | ||
| } | ||
| } | ||
|
|
||
| if (args.json) { | ||
| logger.log( | ||
| JSON.stringify({ preview: previewResource, deployment }, null, 2) | ||
| ); | ||
| } else { | ||
| const scriptLevel = buildMergedScriptLevel(config, previewResource); | ||
| const versionLevel = buildMergedVersionLevel(config, deployment); | ||
| const versionLevel = buildMergedVersionLevel( | ||
| config, | ||
| deployment, | ||
| repositoryUrl, | ||
| pullRequest | ||
| ); | ||
| const configName = configFileName(config.configPath); | ||
| logger.log( | ||
| formatPreviewResource( | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.