-
Notifications
You must be signed in to change notification settings - Fork 3.3k
chore: cy prompt infrastructure #31748
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
Changes from 9 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
2f776b8
feat: cy prompt infrastructure
ryanthemanuel cd1c7e3
refactor and add tests
ryanthemanuel b843dd5
refactor
ryanthemanuel 4ecb321
rename experimental config
ryanthemanuel aca2301
prompt
ryanthemanuel bdbc924
fix test
ryanthemanuel 1e1207e
Merge branch 'feat/cy-prompt' into ryanm/feat/cy-prompt-infra
ryanthemanuel 7740e6b
Update cy-prompt-development.md
ryanthemanuel a620d24
Update cy-prompt-development.md
ryanthemanuel dcd49e8
PR comments
ryanthemanuel 41e08de
Update packages/server/lib/cloud/api/cy-prompt/get_cy_prompt_bundle.ts
ryanthemanuel 04ee86b
PR comments
ryanthemanuel File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,31 @@ | ||
# `cy.prompt` Development | ||
|
||
In production, the code used to facilitate the prompt command will be retrieved from the Cloud. | ||
|
||
To run against locally developed `cy.prompt`: | ||
|
||
- Clone the `cypress-services` repo | ||
- Run `yarn` | ||
- Run `yarn watch` in `app/packages/cy-prompt` | ||
- Set: | ||
- `CYPRESS_INTERNAL_ENV=<environment>` (e.g. `staging` or `production` if you want to hit those deployments of `cypress-services` or `development` if you want to hit a locally running version of `cypress-services`) | ||
- `CYPRESS_LOCAL_CY_PROMPT_PATH` to the path to the `cypress-services/app/packages/cy-prompt/dist/development` directory | ||
- Clone the `cypress` repo | ||
- Run `yarn` | ||
- Run `yarn cypress:open` | ||
- Log In to the Cloud via the App | ||
- Open a project that has `experimentalPromptCommand: true` set in the `e2e` config of the `cypress.config.js|ts` file. | ||
|
||
To run against a deployed version of `cy.prompt`: | ||
|
||
- Set: | ||
- `CYPRESS_INTERNAL_ENV=<environment>` (e.g. `staging` or `production` if you want to hit those deployments of `cypress-services` or `development` if you want to hit a locally running version of `cypress-services`) | ||
``` | ||
|
||
## Testing | ||
|
||
### Unit/Component Testing | ||
|
||
The code that supports cloud `cy.prompt` and lives in the `cypress` monorepo is unit, integration, and e2e tested in a similar fashion to the rest of the code in the repo. See the [contributing guide](https://github.com/cypress-io/cypress/blob/ad353fcc0f7fdc51b8e624a2a1ef4e76ef9400a0/CONTRIBUTING.md?plain=1#L366) for more specifics. | ||
|
||
The code that supports cloud `cy.prompt` and lives in the `cypress-services` monorepo has unit tests that live alongside the code in that monorepo. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
describe('src/cy/commands/prompt', () => { | ||
it('executes the prompt command', () => { | ||
cy.visit('/fixtures/dom.html') | ||
|
||
// TODO: add more tests when cy.prompt is built out, but for now this just | ||
// verifies that the command executes without throwing an error | ||
cy.prompt('Hello, world!') | ||
}) | ||
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { init, loadRemote } from '@module-federation/runtime' | ||
import type{ CyPromptDriverDefaultShape } from './prompt-driver-types' | ||
|
||
interface CyPromptDriver { default: CyPromptDriverDefaultShape } | ||
|
||
let initializedCyPrompt: CyPromptDriverDefaultShape | null = null | ||
const initializeCloudCyPrompt = async (Cypress: Cypress.Cypress): Promise<CyPromptDriverDefaultShape> => { | ||
mschile marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const { success } = await Cypress.backend('wait:for:cy:prompt:ready') | ||
|
||
if (!success) { | ||
throw new Error('CyPromptDriver not found') | ||
} | ||
|
||
init({ | ||
remotes: [{ | ||
alias: 'cy-prompt', | ||
type: 'module', | ||
name: 'cy-prompt', | ||
entryGlobalName: 'cy-prompt', | ||
entry: '/__cypress-cy-prompt/cy-prompt.js', | ||
shareScope: 'default', | ||
}], | ||
name: 'driver', | ||
}) | ||
|
||
const module = await loadRemote<CyPromptDriver>('cy-prompt') | ||
|
||
if (!module?.default) { | ||
throw new Error('CyPromptDriver not found') | ||
} | ||
|
||
initializedCyPrompt = module.default | ||
|
||
return module.default | ||
} | ||
|
||
export default (Commands, Cypress, cy) => { | ||
Commands.addAll({ | ||
async prompt (message: string) { | ||
if (!Cypress.config('experimentalPromptCommand')) { | ||
// TODO: what do we want to do here? | ||
throw new Error('cy.prompt() is not enabled. Please enable it by setting `experimentalPromptCommand: true` in your Cypress config.') | ||
} | ||
|
||
try { | ||
let cloud = initializedCyPrompt | ||
|
||
if (!cloud) { | ||
cloud = await initializeCloudCyPrompt(Cypress) | ||
} | ||
|
||
return await cloud.cyPrompt(Cypress, message) | ||
} catch (error) { | ||
// TODO: handle this better | ||
throw new Error('CyPromptDriver not found') | ||
} | ||
}, | ||
}) | ||
} |
7 changes: 7 additions & 0 deletions
7
packages/driver/src/cy/commands/prompt/prompt-driver-types.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export interface CypressInternal extends Cypress.Cypress { | ||
backend: (eventName: string, ...args: any[]) => Promise<any> | ||
ryanthemanuel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
export interface CyPromptDriverDefaultShape { | ||
cyPrompt: (Cypress: CypressInternal, text: string) => Promise<void> | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 11 additions & 11 deletions
22
...ages/server/lib/StudioLifecycleManager.ts → ...erver/lib/cloud/StudioLifecycleManager.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
64 changes: 64 additions & 0 deletions
64
packages/server/lib/cloud/api/cy-prompt/get_cy_prompt_bundle.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
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 getCyPromptBundle = async ({ cyPromptUrl, projectId, bundlePath }: { cyPromptUrl: string, projectId: string, bundlePath: string }) => { | ||
let responseSignature: string | null = null | ||
|
||
await (asyncRetry(async () => { | ||
const response = await fetch(cyPromptUrl, { | ||
// @ts-expect-error - this is supported | ||
agent, | ||
method: 'GET', | ||
headers: { | ||
'x-route-version': '1', | ||
'x-cypress-signature': PUBLIC_KEY_VERSION, | ||
...(projectId ? { 'x-cypress-project-slug': projectId } : {}), | ||
'x-cypress-cy-prompt-mount-version': '1', | ||
'x-os-name': os.platform(), | ||
'x-cypress-version': pkg.version, | ||
}, | ||
encrypt: 'signed', | ||
}) | ||
|
||
if (!response.ok) { | ||
throw new Error(`Failed to download cy-prompt 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') | ||
ryanthemanuel marked this conversation as resolved.
Show resolved
Hide resolved
ryanthemanuel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.