Skip to content

Commit

Permalink
breaking: make JustInTimeCompile GA from experimentalJustInTimeCompil…
Browse files Browse the repository at this point in the history
…e and default to true (#30641)

* pull support for JIT from vite since it doesn't have an affect for end users or performance (webpack only) [run ci]

rebase this

* remove the experimentalJIT flag and make it GA (default still false) [run ci]

* enable justInTimeCompile by default [run ci]

* chore: bump cache [run ci]
  • Loading branch information
AtofStryker authored Nov 21, 2024
1 parent 39274f4 commit 15c5761
Show file tree
Hide file tree
Showing 61 changed files with 239 additions and 213 deletions.
2 changes: 1 addition & 1 deletion .circleci/cache-version.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Bump this version to force CI to re-create the cache from scratch.

11-19-24-react-19
11-21-24
9 changes: 5 additions & 4 deletions .circleci/workflows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ mainBuildFilters: &mainBuildFilters
- /^release\/\d+\.\d+\.\d+$/
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
- 'update-v8-snapshot-cache-on-develop'
- 'feat/support_react_19'
- 'build-binary-placeholder'
- 'publish-binary'

# usually we don't build Mac app - it takes a long time
Expand All @@ -42,7 +42,7 @@ macWorkflowFilters: &darwin-workflow-filters
- equal: [ develop, << pipeline.git.branch >> ]
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
- equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ]
- equal: [ 'feat/support_react_19', << pipeline.git.branch >> ]
- equal: [ 'build-binary-placeholder', << pipeline.git.branch >> ]
- matches:
pattern: /^release\/\d+\.\d+\.\d+$/
value: << pipeline.git.branch >>
Expand All @@ -53,7 +53,7 @@ linuxArm64WorkflowFilters: &linux-arm64-workflow-filters
- equal: [ develop, << pipeline.git.branch >> ]
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
- equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ]
- equal: [ 'feat/support_react_19', << pipeline.git.branch >> ]
- equal: [ 'build-binary-placeholder', << pipeline.git.branch >> ]
- matches:
pattern: /^release\/\d+\.\d+\.\d+$/
value: << pipeline.git.branch >>
Expand All @@ -76,6 +76,7 @@ windowsWorkflowFilters: &windows-workflow-filters
- equal: [ develop, << pipeline.git.branch >> ]
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
- equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ]
- equal: [ 'build-binary-placeholder', << pipeline.git.branch >> ]
- matches:
pattern: /^release\/\d+\.\d+\.\d+$/
value: << pipeline.git.branch >>
Expand Down Expand Up @@ -151,7 +152,7 @@ commands:
name: Set environment variable to determine whether or not to persist artifacts
command: |
echo "Setting SHOULD_PERSIST_ARTIFACTS variable"
echo 'if ! [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "feat/support_react_19" ]]; then
echo 'if ! [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "build-binary-placeholder" ]]; then
export SHOULD_PERSIST_ARTIFACTS=true
fi' >> "$BASH_ENV"
# You must run `setup_should_persist_artifacts` command and be using bash before running this command
Expand Down
3 changes: 3 additions & 0 deletions cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ _Released 12/3/2024 (PENDING)_
- The undocumented methods `Cypress.backend('firefox:force:gc')` and `Cypress.backend('log:memory:pressure')` were removed. Addresses [#30222](https://github.com/cypress-io/cypress/issues/30222).
- Upgraded bundled Node.js version from `18.17.0` to `20.18.0`. Addresses [#29547](https://github.com/cypress-io/cypress/issues/29547).
- It is no longer possible to make a `fetch` or `XMLHttpRequest` request from the `about:blank` page in Electron (i.e. `cy.window().then((win) => win.fetch('<some-url>')`). You must use `cy.request` instead or perform some form of initial navigation via `cy.visit()`. Addressed in [#29547](https://github.com/cypress-io/cypress/pull/30394).
- The
`experimentalJustInTimeCompile`
configuration option for component testing has been replaced with a `justInTimeCompile` option that is `true` by default. This option will only compile resources directly related to your spec, compiling them 'just-in-time' before spec execution. This should result in improved memory management and performance for component tests in `cypress open` and `cypress run` modes, in particular for large component testing suites. `justInTimeCompile` is now only supported for [`webpack`](https://www.npmjs.com/package/webpack). Addresses [#30234](https://github.com/cypress-io/cypress/issues/30234). Addressed in [#30402](https://github.com/cypress-io/cypress/pull/30402).
- `@cypress/webpack-dev-server` no longer supports `webpack-dev-server` version 3. Additionally, `@cypress/webpack-dev-server` now ships with `webpack-dev-server` version 5 by default. `webpack-dev-server` version 4 will need to be installed along side Cypress if you are still using `webpack` version 4. Addresses [#29308](https://github.com/cypress-io/cypress/issues/29308), [#30347](https://github.com/cypress-io/cypress/issues/30347), and [#30141](https://github.com/cypress-io/cypress/issues/30141).
- `@cypress/vite-dev-server` no longer supports `vite` versions 2 and 3. Addresses [#29377](https://github.com/cypress-io/cypress/issues/29377) and [#29378](https://github.com/cypress-io/cypress/issues/29378).
- Cypress Component Testing no longer supports `React` versions 16 and 17. Addresses [#29607](https://github.com/cypress-io/cypress/issues/29607).
Expand Down
16 changes: 8 additions & 8 deletions cli/types/cypress.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3113,14 +3113,6 @@ declare namespace Cypress {
* @default null
*/
experimentalSkipDomainInjection: string[] | null
/**
* Allows for just-in-time compiling of a component test, which will only compile assets related to the component.
* This results in a smaller bundle under test, reducing resource constraints on a given machine. This option is recommended
* for users with large component testing projects and those who are running into webpack 'chunk load error' issues.
* Supported for vite and webpack. For component testing only.
* @see https://on.cypress.io/experiments#Configuration
*/
experimentalJustInTimeCompile: boolean
/**
* Enables AST-based JS/HTML rewriting. This may fix issues caused by the existing regex-based JS/HTML replacement algorithm.
* @default false
Expand All @@ -3141,6 +3133,14 @@ declare namespace Cypress {
* @default false
*/
experimentalMemoryManagement: boolean
/**
* Allows for just-in-time compiling of a component test, which will only compile assets related to the component.
* This results in a smaller bundle under test, reducing resource constraints on a given machine. This option is recommended
* for users with large component testing projects and those who are running into webpack 'chunk load error' issues.
* Supported for webpack-dev-server only. For component testing only.
* @see https://on.cypress.io/experiments#Configuration
*/
justInTimeCompile: boolean
/**
* Number of times to retry a failed test.
* If a number is set, tests will retry in both runMode and openMode.
Expand Down
7 changes: 6 additions & 1 deletion npm/vite-dev-server/src/plugins/cypress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,12 @@ export const Cypress = (
// eslint-disable-next-line no-restricted-syntax
let loader = fs.readFileSync(INIT_FILEPATH, 'utf8')

devServerEvents.on('dev-server:specs:changed', (specs: Spec[]) => {
devServerEvents.on('dev-server:specs:changed', ({ specs, options }: { specs: Spec[], options?: { neededForJustInTimeCompile: boolean }}) => {
if (options?.neededForJustInTimeCompile) {
// if an option is needed for just in time compile, no-op as this isn't supported in vite
return
}

debug(`dev-server:secs:changed: ${specs.map((spec) => spec.relative)}`)
specsPathsSet = getSpecsPathsSet(specs)
})
Expand Down
4 changes: 1 addition & 3 deletions npm/vite-dev-server/src/resolveConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ export const createViteDevServerConfig = async (config: ViteDevServerConfig, vit
function makeCypressViteConfig (config: ViteDevServerConfig, vite: Vite): InlineConfig | InlineConfig {
const {
cypressConfig: {
experimentalJustInTimeCompile,
port,
projectRoot,
devServerPublicPathRoute,
Expand Down Expand Up @@ -129,8 +128,7 @@ function makeCypressViteConfig (config: ViteDevServerConfig, vite: Vite): Inline
port: vitePort,
host: '127.0.0.1',
// Disable file watching and HMR when executing tests in `run` mode
// if experimentalJustInTimeCompile is configured, we need to watch for file changes as the spec entries are going to be updated per test in run mode
...(isTextTerminal && !experimentalJustInTimeCompile
...(isTextTerminal
? { watch: { ignored: '**/*' }, hmr: false }
: {}),
},
Expand Down
35 changes: 0 additions & 35 deletions npm/vite-dev-server/test/resolveConfig.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,40 +109,5 @@ describe('resolveConfig', function () {
expect(viteConfig.server?.hmr).to.be.undefined
})
})

describe('experimentalJustInTimeCompile', () => {
let viteDevServerConfig: ViteDevServerConfig

beforeEach(async () => {
const projectRoot = await scaffoldSystemTestProject(`vite${version}-inspect`)

viteDevServerConfig = getViteDevServerConfig(projectRoot)
viteDevServerConfig.cypressConfig.experimentalJustInTimeCompile = true
})

describe('open mode', () => {
beforeEach(() => {
viteDevServerConfig.cypressConfig.isTextTerminal = false
})

it('enables hmr and watching', async () => {
const viteConfig = await createViteDevServerConfig(viteDevServerConfig, discoveredVite)

expect(viteConfig.server.watch).to.be.undefined
})
})

describe('run mode', () => {
beforeEach(() => {
viteDevServerConfig.cypressConfig.isTextTerminal = true
})

it('enables hmr and watching', async () => {
const viteConfig = await createViteDevServerConfig(viteDevServerConfig, discoveredVite)

expect(viteConfig.server.watch).to.be.undefined
})
})
})
})
})
2 changes: 1 addition & 1 deletion npm/webpack-dev-server/src/CypressCTWebpackPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export class CypressCTWebpackPlugin {
*
* See https://github.com/cypress-io/cypress/issues/24398
*/
private onSpecsChange = async (specs: Cypress.Cypress['spec'][]) => {
private onSpecsChange = async ({ specs, options }: { specs: Cypress.Cypress['spec'][], options?: { neededForJustInTimeCompile: boolean}}) => {
if (!this.compilation || _.isEqual(specs, this.files)) {
return
}
Expand Down
6 changes: 3 additions & 3 deletions npm/webpack-dev-server/src/makeDefaultWebpackConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function makeCypressWebpackConfig (
const {
devServerConfig: {
cypressConfig: {
experimentalJustInTimeCompile,
justInTimeCompile,
port,
projectRoot,
devServerPublicPathRoute,
Expand Down Expand Up @@ -100,8 +100,8 @@ export function makeCypressWebpackConfig (
} as any

if (isRunMode) {
// if experimentalJustInTimeCompile is configured, we need to watch for file changes as the spec entries are going to be updated per test
const ignored = experimentalJustInTimeCompile ? /node_modules/ : '**/*'
// if justInTimeCompile is configured, we need to watch for file changes as the spec entries are going to be updated per test
const ignored = justInTimeCompile ? /node_modules/ : '**/*'

// Disable file watching when executing tests in `run` mode
finalConfig.watchOptions = {
Expand Down
7 changes: 5 additions & 2 deletions npm/webpack-dev-server/src/makeWebpackConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,18 @@ export async function makeWebpackConfig (
) {
let userWebpackConfig = config.devServerConfig.webpackConfig
const frameworkWebpackConfig = config.frameworkConfig as Partial<Configuration>

const {
cypressConfig: {
projectRoot,
supportFile,
justInTimeCompile,
},
specs: files,
framework,
} = config.devServerConfig

config.devServerConfig.specs = justInTimeCompile ? [] : config.devServerConfig.specs

if (!userWebpackConfig && !frameworkWebpackConfig) {
debug('Not user or framework webpack config received. Trying to automatically source it')

Expand Down Expand Up @@ -121,7 +124,7 @@ export async function makeWebpackConfig (
)

debug(`User passed in user and framework webpack config with values %o`, userAndFrameworkWebpackConfig)
debug(`New webpack entries %o`, files)
debug(`New webpack entries %o`, config.devServerConfig.specs)
debug(`Project root`, projectRoot)
debug(`Support file`, supportFile)

Expand Down
4 changes: 3 additions & 1 deletion npm/webpack-dev-server/test/devServer-e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,9 @@ describe('#devServer', () => {
const oldmtime = fs.statSync(cypressConfig.indexHtmlFile).mtimeMs

await once(devServerEvents, 'dev-server:compile:success')
devServerEvents.emit('dev-server:specs:changed', [newSpec])
devServerEvents.emit('dev-server:specs:changed', {
specs: [newSpec],
})

await once(devServerEvents, 'dev-server:compile:success')
const updatedmtime = fs.statSync(cypressConfig.indexHtmlFile).mtimeMs
Expand Down
4 changes: 2 additions & 2 deletions npm/webpack-dev-server/test/makeWebpackConfig.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ describe('makeWebpackConfig', () => {
})
})

describe('experimentalJustInTimeCompile', () => {
describe('justInTimeCompile', () => {
let devServerConfig: WebpackDevServerConfig

const WEBPACK_MATRIX: {
Expand All @@ -419,7 +419,7 @@ describe('makeWebpackConfig', () => {
cypressConfig: {
projectRoot: '.',
devServerPublicPathRoute: '/test-public-path',
experimentalJustInTimeCompile: true,
justInTimeCompile: true,
baseUrl: null,
} as Cypress.PluginConfigOptions,
webpackConfig: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ import type { fixtureDirs } from '@tooling/system-tests'

type ProjectDirs = typeof fixtureDirs

const EXPERIMENTAL_JIT_DIR: ProjectDirs[number] = 'experimental-JIT'
const JIT_DIR: ProjectDirs[number] = 'justInTimeCompile'

const PROJECTS: {bundler: 'vite' | 'webpack'}[] = [
// when running for vite, justInTimeCompile=true is set but is a no-op for vite since JIT compiling is not supported in vite
{ bundler: 'vite' },
{ bundler: 'webpack' },
]

for (const { bundler } of PROJECTS) {
const PROJECT_NAME = `${EXPERIMENTAL_JIT_DIR}/${bundler}`
const PROJECT_NAME = `${JIT_DIR}/${bundler}`

describe(`CT experimentalJustInTimeCompile: ${bundler}`, { viewportWidth: 1500, defaultCommandTimeout: 30000 }, () => {
describe(`CT justInTimeCompile: ${bundler}`, { viewportWidth: 1500, defaultCommandTimeout: 30000 }, () => {
const visitComponentSpecAndVerifyPass = (specNumber: number) => {
cy.contains(`Component-${specNumber}.cy.jsx`).click()
cy.waitForSpecToFinish(undefined)
Expand Down
4 changes: 2 additions & 2 deletions packages/app/src/runner/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -445,8 +445,8 @@ async function executeSpec (spec: SpecFile, isRerun: boolean = false) {
}

if (window.__CYPRESS_TESTING_TYPE__ === 'component') {
if (config.experimentalJustInTimeCompile && !config.isTextTerminal) {
// If running with experimentalJustInTimeCompile enabled and in open mode,
if (config.justInTimeCompile && !config.isTextTerminal) {
// If running with justInTimeCompile enabled and in open mode,
// send a signal to the dev server to load the spec before running
// since the spec and related resources are not yet compiled.
await updateDevServerWithSpec(spec)
Expand Down
7 changes: 4 additions & 3 deletions packages/config/__snapshots__/index.spec.ts.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ exports['config/src/index .getBreakingKeys returns list of breaking config keys
'componentFolder',
'experimentalComponentTesting',
'experimentalGetCookiesSameSite',
'experimentalJustInTimeCompile',
'experimentalNetworkStubbing',
'experimentalRunEvents',
'experimentalSessionSupport',
Expand Down Expand Up @@ -39,7 +40,6 @@ exports['config/src/index .getDefaultValues returns list of public config keys 1
'experimentalMemoryManagement': false,
'experimentalModifyObstructiveThirdPartyCode': false,
'experimentalSkipDomainInjection': null,
'experimentalJustInTimeCompile': false,
'experimentalOriginDependencies': false,
'experimentalSourceRewriting': false,
'experimentalSingleTabRunMode': false,
Expand All @@ -49,6 +49,7 @@ exports['config/src/index .getDefaultValues returns list of public config keys 1
'fixturesFolder': 'cypress/fixtures',
'excludeSpecPattern': '*.hot-update.js',
'includeShadowDom': false,
'justInTimeCompile': true,
'keystrokeDelay': 0,
'modifyObstructiveCode': true,
'numTestsKeptInMemory': 50,
Expand Down Expand Up @@ -129,7 +130,6 @@ exports['config/src/index .getDefaultValues returns list of public config keys f
'experimentalMemoryManagement': false,
'experimentalModifyObstructiveThirdPartyCode': false,
'experimentalSkipDomainInjection': null,
'experimentalJustInTimeCompile': false,
'experimentalOriginDependencies': false,
'experimentalSourceRewriting': false,
'experimentalSingleTabRunMode': false,
Expand All @@ -139,6 +139,7 @@ exports['config/src/index .getDefaultValues returns list of public config keys f
'fixturesFolder': 'cypress/fixtures',
'excludeSpecPattern': '*.hot-update.js',
'includeShadowDom': false,
'justInTimeCompile': true,
'keystrokeDelay': 0,
'modifyObstructiveCode': true,
'numTestsKeptInMemory': 50,
Expand Down Expand Up @@ -215,7 +216,6 @@ exports['config/src/index .getPublicConfigKeys returns list of public config key
'experimentalMemoryManagement',
'experimentalModifyObstructiveThirdPartyCode',
'experimentalSkipDomainInjection',
'experimentalJustInTimeCompile',
'experimentalOriginDependencies',
'experimentalSourceRewriting',
'experimentalSingleTabRunMode',
Expand All @@ -225,6 +225,7 @@ exports['config/src/index .getPublicConfigKeys returns list of public config key
'fixturesFolder',
'excludeSpecPattern',
'includeShadowDom',
'justInTimeCompile',
'keystrokeDelay',
'modifyObstructiveCode',
'numTestsKeptInMemory',
Expand Down
24 changes: 14 additions & 10 deletions packages/config/src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,12 +231,6 @@ const driverConfigOptions: Array<DriverConfigOption> = [
validation: validate.isNullOrArrayOfStrings,
isExperimental: true,
requireRestartOnChange: 'server',
}, {
name: 'experimentalJustInTimeCompile',
defaultValue: false,
validation: validate.isBoolean,
isExperimental: true,
requireRestartOnChange: 'server',
}, {
name: 'experimentalOriginDependencies',
defaultValue: false,
Expand Down Expand Up @@ -290,6 +284,11 @@ const driverConfigOptions: Array<DriverConfigOption> = [
defaultValue: false,
validation: validate.isBoolean,
overrideLevel: 'any',
}, {
name: 'justInTimeCompile',
defaultValue: true,
validation: validate.isBoolean,
requireRestartOnChange: 'server',
}, {
name: 'keystrokeDelay',
defaultValue: 0,
Expand Down Expand Up @@ -632,6 +631,11 @@ export const breakingOptions: Readonly<BreakingOption[]> = [
errorKey: 'EXPERIMENTAL_SAMESITE_REMOVED',
isWarning: true,
}, {
name: 'experimentalJustInTimeCompile',
errorKey: 'EXPERIMENTAL_JIT_COMPILE_REMOVED',
isWarning: true,
},
{
name: 'experimentalNetworkStubbing',
errorKey: 'EXPERIMENTAL_NETWORK_STUBBING_REMOVED',
isWarning: true,
Expand Down Expand Up @@ -736,8 +740,8 @@ export const breakingRootOptions: Array<BreakingOption> = [
testingTypes: ['e2e'],
},
{
name: 'experimentalJustInTimeCompile',
errorKey: 'EXPERIMENTAL_JIT_COMPONENT_TESTING',
name: 'justInTimeCompile',
errorKey: 'JIT_COMPONENT_TESTING',
isWarning: false,
testingTypes: ['component'],
},
Expand All @@ -756,8 +760,8 @@ export const testingTypeBreakingOptions: { e2e: Array<BreakingOption>, component
isWarning: false,
},
{
name: 'experimentalJustInTimeCompile',
errorKey: 'EXPERIMENTAL_JIT_COMPONENT_TESTING',
name: 'justInTimeCompile',
errorKey: 'JIT_COMPONENT_TESTING',
isWarning: false,
},
],
Expand Down
Loading

4 comments on commit 15c5761

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 15c5761 Nov 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux x64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/13.15.2/linux-x64/release/14.0.0-15c5761eb6efa396f575434153ebb3c1300f2aff/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 15c5761 Nov 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux arm64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/13.15.2/linux-arm64/release/14.0.0-15c5761eb6efa396f575434153ebb3c1300f2aff/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 15c5761 Nov 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin arm64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/13.15.2/darwin-arm64/release/14.0.0-15c5761eb6efa396f575434153ebb3c1300f2aff/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 15c5761 Nov 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin x64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/13.15.2/darwin-x64/release/14.0.0-15c5761eb6efa396f575434153ebb3c1300f2aff/cypress.tgz

Please sign in to comment.