Skip to content

internal: (studio) set up hot reloading for the studio bundle #31796

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

Merged
merged 21 commits into from
May 30, 2025
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

62 changes: 62 additions & 0 deletions packages/server/lib/cloud/api/studio/get_studio_bundle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { asyncRetry, linearDelay } from '../../../util/async_retry'
import { isRetryableError } from '../../network/is_retryable_error'
import fetch from 'cross-fetch'
import os from 'os'
import { agent } from '@packages/network'
import { PUBLIC_KEY_VERSION } from '../../constants'
import { createWriteStream } from 'fs'
import { verifySignatureFromFile } from '../../encryption'

const pkg = require('@packages/root')
const _delay = linearDelay(500)

export const getStudioBundle = async ({ studioUrl, projectId, bundlePath }: { studioUrl: string, projectId?: string, bundlePath: string }) => {
let responseSignature: string | null = null

await (asyncRetry(async () => {
const response = await fetch(studioUrl, {
// @ts-expect-error - this is supported
agent,
method: 'GET',
headers: {
'x-route-version': '1',
'x-cypress-signature': PUBLIC_KEY_VERSION,
'x-os-name': os.platform(),
'x-cypress-version': pkg.version,
},
encrypt: 'signed',
})

if (!response.ok) {
throw new Error(`Failed to download studio bundle: ${response.statusText}`)
}

responseSignature = response.headers.get('x-cypress-signature')

await new Promise<void>((resolve, reject) => {
const writeStream = createWriteStream(bundlePath)

writeStream.on('error', reject)
writeStream.on('finish', () => {
resolve()
})

// @ts-expect-error - this is supported
response.body?.pipe(writeStream)
})
}, {
maxAttempts: 3,
retryDelay: _delay,
shouldRetry: isRetryableError,
}))()

if (!responseSignature) {
throw new Error('Unable to get studio signature')
}

const verified = await verifySignatureFromFile(bundlePath, responseSignature)

if (!verified) {
throw new Error('Unable to verify studio signature')
}
}
4 changes: 2 additions & 2 deletions packages/server/lib/cloud/api/studio/post_studio_session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import { agent } from '@packages/network'
const pkg = require('@packages/root')
const routes = require('../../routes') as typeof import('../../routes')

interface GetStudioSessionOptions {
interface PostStudioSessionOptions {
projectId?: string
}

const _delay = linearDelay(500)

export const postStudioSession = async ({ projectId }: GetStudioSessionOptions) => {
export const postStudioSession = async ({ projectId }: PostStudioSessionOptions) => {
return await (asyncRetry(async () => {
const response = await fetch(routes.apiRoutes.studioSession(), {
// @ts-expect-error - this is supported
Expand Down
12 changes: 12 additions & 0 deletions packages/server/lib/cloud/get_cloud_metadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { CloudDataSource } from '@packages/data-context/src/sources'

export const getCloudMetadata = async (cloudDataSource: CloudDataSource) => {
const cloudEnv = (process.env.CYPRESS_CONFIG_ENV || process.env.CYPRESS_INTERNAL_ENV || 'production') as 'development' | 'staging' | 'production'
const cloudUrl = cloudDataSource.getCloudUrl(cloudEnv)
const cloudHeaders = await cloudDataSource.additionalHeaders()

return {
cloudUrl,
cloudHeaders,
}
}
Loading
Loading