diff --git a/WORKSPACE b/WORKSPACE index ca7f5fb3ad..a24b2aa0d4 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -120,6 +120,8 @@ load("//packages/cypress:index.bzl", "cypress_repository") cypress_repository( name = "cypress", cypress_bin = "@cypress_deps//:node_modules/cypress/bin/cypress", + # Currently cypress cannot be installed on our Linux/Windows CI machines + fail_on_error = False, ) # diff --git a/packages/cypress/BUILD.bazel b/packages/cypress/BUILD.bazel index ef7b3dc563..8cdb6fdd73 100644 --- a/packages/cypress/BUILD.bazel +++ b/packages/cypress/BUILD.bazel @@ -76,8 +76,8 @@ pkg_npm( srcs = [ "index.bzl", "package.json", - "//packages/cypress:internal/cypress-install.js", "//packages/cypress:internal/cypress_repository.bzl", + "//packages/cypress:internal/install-cypress.js", "//packages/cypress:internal/plugins/base.js", "//packages/cypress:internal/plugins/index.template.js", "//packages/cypress:internal/run-cypress.js", @@ -90,8 +90,8 @@ pkg_npm( "plugins/base.js", ])""", substitutions = { - "@build_bazel_rules_nodejs//packages/cypress:internal/cypress-install.js": "TEMPLATED_node_modules_workspace_name//@bazel/cypress:internal/cypress-install.js", "@build_bazel_rules_nodejs//packages/cypress:internal/cypress_repository.bzl": "//packages/cypress:internal/cypress_repository.bzl", + "@build_bazel_rules_nodejs//packages/cypress:internal/install-cypress.js": "TEMPLATED_node_modules_workspace_name//@bazel/cypress:internal/install-cypress.js", "@build_bazel_rules_nodejs//packages/cypress:internal/plugins/base.js": "TEMPLATED_node_modules_workspace_name//@bazel/cypress:internal/plugins/base.js", "@build_bazel_rules_nodejs//packages/cypress:internal/plugins/index.template.js": "TEMPLATED_node_modules_workspace_name//@bazel/cypress:internal/plugins/index.template.js", "@build_bazel_rules_nodejs//packages/cypress:internal/run-cypress.js": "TEMPLATED_node_modules_workspace_name//@bazel/cypress:internal/run-cypress.js", diff --git a/packages/cypress/internal/cypress_repository.bzl b/packages/cypress/internal/cypress_repository.bzl index c767cc15d8..0c06c2ceba 100644 --- a/packages/cypress/internal/cypress_repository.bzl +++ b/packages/cypress/internal/cypress_repository.bzl @@ -20,10 +20,10 @@ load("@build_bazel_rules_nodejs//internal/node:node_labels.bzl", "get_node_label def _cypress_repository_impl(repository_ctx): node = repository_ctx.path(get_node_label(repository_ctx)) - cypress_install = "packages/cypress/internal/cypress-install.js" + install_cypress = "packages/cypress/internal/install-cypress.js" repository_ctx.template( - cypress_install, - repository_ctx.path(repository_ctx.attr._cypress_install), + install_cypress, + repository_ctx.path(repository_ctx.attr._install_cypress), {}, ) @@ -36,10 +36,13 @@ def _cypress_repository_impl(repository_ctx): ) exec_result = repository_ctx.execute( - [node, cypress_install, repository_ctx.path(repository_ctx.attr.cypress_bin)], + [node, install_cypress, repository_ctx.path(repository_ctx.attr.cypress_bin)], quiet = repository_ctx.attr.quiet, ) + if exec_result.return_code != 0 and repository_ctx.attr.fail_on_error: + fail("\ncypress_repository exited with code: {}\n\nstdout:\n{}\n\nstderr:\n{}\n\n".format(exec_result.return_code, exec_result.stdout, exec_result.stderr)) + cypress_repository = repository_rule( implementation = _cypress_repository_impl, attrs = { @@ -48,17 +51,21 @@ cypress_repository = repository_rule( allow_single_file = True, default = "@npm//:node_modules/cypress/bin/cypress", ), + "fail_on_error": attr.bool( + default = True, + doc = "If the repository rule should allow errors", + ), "quiet": attr.bool( default = True, doc = "If stdout and stderr should be printed to the terminal", ), - "_cypress_install": attr.label( - allow_single_file = True, - default = "//packages/cypress:internal/cypress-install.js", - ), "_cypress_web_test": attr.label( allow_single_file = True, default = "//packages/cypress:internal/template.cypress_web_test.bzl", ), + "_install_cypress": attr.label( + allow_single_file = True, + default = "//packages/cypress:internal/install-cypress.js", + ), }, ) diff --git a/packages/cypress/internal/cypress-install.js b/packages/cypress/internal/install-cypress.js similarity index 94% rename from packages/cypress/internal/cypress-install.js rename to packages/cypress/internal/install-cypress.js index 8d52c3b8f4..e8267088ee 100644 --- a/packages/cypress/internal/cypress-install.js +++ b/packages/cypress/internal/install-cypress.js @@ -1,5 +1,5 @@ /** - * cypress-install is responsible for creating an external repository from which a cypress_web_test + * install-cypress is responsible for creating an external repository from which a cypress_web_test * can be loaded. The script invokes `cypress install` to download and install the cypress binary * and subsequently calls cypress verify to ensure the binary is runnable. * @@ -47,7 +47,12 @@ exports_files([ _cypress_web_test = "cypress_web_test_global_cache", ) cypress_web_test = _cypress_web_test`) + + const env = { + PATH: `${dirname(nodePath)}:${process.env.PATH}`, + }; const spawnOptions = { + env, stdio: [process.stdin, process.stdout, process.stderr], shell: process.env.SHELL }; @@ -71,6 +76,7 @@ function installSandboxedCypressCache() { const env = { CYPRESS_CACHE_FOLDER: join(cwd, 'cypress-cache'), PATH: `${dirname(nodePath)}:${process.env.PATH}`, + DEBUG: 'cypress:*' } const spawnOptions = @@ -91,9 +97,7 @@ function installSandboxedCypressCache() { }; let CYPRESS_RUN_BINARY; - const cacheFiles = []; walkDir(env.CYPRESS_CACHE_FOLDER, (filePath) => { - cacheFiles.push(filePath); if (basename(filePath) === 'Cypress') { if (CYPRESS_RUN_BINARY) { throw new Error(`More than one cypress executable found: ${CYPRESS_RUN_BINARY} ${filePath}`) @@ -107,12 +111,19 @@ function installSandboxedCypressCache() { throw new Error(`No cypress executable found.`); } - const verify = spawnSync(`${cypressBin}`, ['verify'], spawnOptions); + spawnOptions.env.CYPRESS_RUN_BINARY = CYPRESS_RUN_BINARY; + + const verify = spawnSync(cypressBin, ['verify'], spawnOptions); if (verify.status !== 0) { throw new Error(`cypress verify failed`); } + const cacheFiles = []; + walkDir(env.CYPRESS_CACHE_FOLDER, (filePath) => { + cacheFiles.push(filePath); + }); + writeFileSync('index.bzl', `load( "//:packages/cypress/internal/cypress_web_test.bzl", _cypress_web_test = "cypress_web_test", diff --git a/packages/cypress/internal/plugins/index.template.js b/packages/cypress/internal/plugins/index.template.js index 0f403dd581..48d7c0463e 100644 --- a/packages/cypress/internal/plugins/index.template.js +++ b/packages/cypress/internal/plugins/index.template.js @@ -1,5 +1,4 @@ -const fs = require('fs'); -const {join, basename, normalize} = require('path'); +const {join, normalize} = require('path'); const basePluginShortPath = 'TEMPLATED_pluginsFile'; const integrationFileShortPaths = TEMPLATED_integrationFileShortPaths; @@ -12,31 +11,27 @@ const browserifyFactory = require(normalize(`TEMPLATED_@cypress/browserify-prepr const browserify = browserifyFactory(browserifyFactory.defaultOptions); module.exports = (on, config) => { - // Load in the user's cypress plugin - config = basePlugin(on, config); + // Set env variables needed usually set by for `bazel test` invocations + // (they are not set automatically for `bazel run`). + process.env.RUNFILES_DIR = process.env.RUNFILES_DIR || join(cwd, '../'); + process.env.RUNFILES_MANIFEST_FILE = + process.env.RUNFILES_MANIFEST_FILE || join(cwd, '../', 'MANIFEST'); // Set test files to tests passed as `srcs` config.integrationFolder = cwd; config.testFiles = integrationFileShortPaths; - // Set screenshots folder to a writable directory - const screenshotsFolder = join(process.env['TEST_UNDECLARED_OUTPUTS_DIR'], 'screenshots'); - fs.mkdirSync(screenshotsFolder); - config.screenshotsFolder = screenshotsFolder; - - // Set videos folder to a writable directory - const videosFolder = join(process.env['TEST_UNDECLARED_OUTPUTS_DIR'], 'videos'); - fs.mkdirSync(videosFolder); - config.videosFolder = videosFolder; - - // Chrome sandboxing must be disabled for execution during bazel test. - config.chromeWebSecurity = false; + // Set screenshots/videos folder to a writable directory + config.screenshotsFolder = process.env['TEST_UNDECLARED_OUTPUTS_DIR'] || process.env.RUNFILES_DIR; + config.videosFolder = process.env['TEST_UNDECLARED_OUTPUTS_DIR'] || process.env.RUNFILES_DIR; // Set file preprocessing output path to writable directory. on('file:preprocessor', (file) => { - file.outputPath = join(process.env['TEST_UNDECLARED_OUTPUTS_DIR'], basename(file.outputPath)); + file.outputPath = + join(process.env['TEST_TMPDIR'], file.outputPath.split('/bundles/').slice(1).join()); return browserify(file); }); - return config; + // Load in the user's cypress plugin + return basePlugin(on, config); }; diff --git a/packages/cypress/internal/run-cypress.js b/packages/cypress/internal/run-cypress.js index cab1cb579a..ebeeec6567 100644 --- a/packages/cypress/internal/run-cypress.js +++ b/packages/cypress/internal/run-cypress.js @@ -7,11 +7,11 @@ const [node, entry, configFilePath, pluginsFilePath, cypressExecutable, ...args] if (cypressExecutable) { process.env.CYPRESS_RUN_BINARY = join(process.cwd(), cypressExecutable.replace('external/', '../')); + process.env.CYPRESS_CACHE_FOLDER = + join(process.env.CYPRESS_RUN_BINARY.split('/cypress-cache/')[0], '/cypress-cache'); + process.env.HOME = process.env['TEST_TMPDIR']; } -console.log(process.argv); - - const pluginsFile = runfiles.resolveWorkspaceRelative(pluginsFilePath).replace(process.cwd(), '.'); const configFile = runfiles.resolveWorkspaceRelative(configFilePath).replace(process.cwd(), '.'); diff --git a/packages/cypress/internal/template.cypress_web_test.bzl b/packages/cypress/internal/template.cypress_web_test.bzl index bb25198b46..73f113b908 100644 --- a/packages/cypress/internal/template.cypress_web_test.bzl +++ b/packages/cypress/internal/template.cypress_web_test.bzl @@ -41,8 +41,6 @@ def _cypress_plugin_impl(ctx): template = ctx.file._plugin_template, substitutions = { "TEMPLATED_@cypress/browserify-preprocessor": "${cwd}/../cypress_deps/node_modules/@cypress/browserify-preprocessor/index", - "TEMPLATED_includeScreenshots": "true" if ctx.attr.include_screenshots else "false", - "TEMPLATED_includeVideos": "true" if ctx.attr.include_video else "false", "TEMPLATED_integrationFileShortPaths": "[\n {files}\n]".format(files = ",\n ".join(integration_files_short_paths)), "TEMPLATED_pluginsFile": plugins_file.short_path, }, @@ -52,13 +50,6 @@ def _cypress_plugin_impl(ctx): files = depset([ctx.outputs.plugin]), )] -# Avoid using non-normalized paths (workspace/../other_workspace/path) -def _to_manifest_path(ctx, file): - if file.short_path.startswith("../"): - return file.short_path[3:] - else: - return ctx.workspace_name + "/" + file.short_path - _cypress_plugin = rule( implementation = _cypress_plugin_impl, outputs = {"plugin": "%{name}_cypress_plugin.js"}, @@ -67,8 +58,6 @@ _cypress_plugin = rule( allow_single_file = [".json"], mandatory = True, ), - "include_screenshots": attr.bool(default = False), - "include_video": attr.bool(default = False), "plugins_file": attr.label( default = Label("@build_bazel_rules_nodejs//packages/cypress:internal/plugins/base.js"), allow_single_file = True, @@ -89,8 +78,6 @@ def cypress_web_test( name, config_file, srcs = [], - include_screenshots = False, - include_video = False, plugins_file = Label("@build_bazel_rules_nodejs//packages/cypress:internal/plugins/base.js"), cypress = Label("TEMPLATED_node_modules_workspace_name//cypress:cypress"), cypress_browserify_preprocessor = Label("TEMPLATED_node_modules_workspace_name//@cypress/browserify-preprocessor"), @@ -106,8 +93,6 @@ def cypress_web_test( name = cypress_plugin, srcs = srcs, tags = tags, - include_screenshots = include_screenshots, - include_video = include_video, plugins_file = plugins_file, config_file = config_file, testonly = True, @@ -123,14 +108,14 @@ def cypress_web_test( cypress_browserify_preprocessor, cypress_cache, cypress_executable, - ":{cypress_plugin}".format(cypress_plugin = cypress_plugin), - ":{config_file}".format(config_file = config_file), + "{cypress_plugin}".format(cypress_plugin = cypress_plugin), + "{config_file}".format(config_file = config_file), ] + srcs, entry_point = "@build_bazel_rules_nodejs//packages/cypress:internal/run-cypress.js", templated_args = [ "--nobazel_patch_module_resolver", - "$(rootpath :{config_file})".format(config_file = config_file), - "$(rootpath :{cypress_plugin})".format(cypress_plugin = cypress_plugin), + "$(rootpath {config_file})".format(config_file = config_file), + "$(rootpath {cypress_plugin})".format(cypress_plugin = cypress_plugin), "$(rootpath {cypress_executable})".format(cypress_executable = cypress_executable), ] + templated_args, **kwargs @@ -140,8 +125,6 @@ def cypress_web_test_global_cache( name, config_file, srcs = [], - include_screenshots = False, - include_video = False, plugins_file = Label("@build_bazel_rules_nodejs//packages/cypress:plugins/base.js"), cypress = Label("TEMPLATED_node_modules_workspace_name//cypress:cypress"), cypress_browserify_preprocessor = Label("TEMPLATED_node_modules_workspace_name//@cypress/browserify-preprocessor"), @@ -155,8 +138,6 @@ def cypress_web_test_global_cache( name = cypress_plugin, srcs = srcs, tags = tags, - include_screenshots = include_screenshots, - include_video = include_video, plugins_file = plugins_file, config_file = config_file, testonly = True, @@ -170,14 +151,14 @@ def cypress_web_test_global_cache( plugins_file, cypress, cypress_browserify_preprocessor, - ":{cypress_plugin}".format(cypress_plugin = cypress_plugin), - ":{config_file}".format(config_file = config_file), + "{cypress_plugin}".format(cypress_plugin = cypress_plugin), + "{config_file}".format(config_file = config_file), ] + srcs, entry_point = "@build_bazel_rules_nodejs//packages/cypress:internal/run-cypress.js", templated_args = [ "--nobazel_patch_module_resolver", - "$(rootpath :{config_file})".format(config_file = config_file), - "$(rootpath :{cypress_plugin})".format(cypress_plugin = cypress_plugin), + "$(rootpath {config_file})".format(config_file = config_file), + "$(rootpath {cypress_plugin})".format(cypress_plugin = cypress_plugin), ] + templated_args, **kwargs )