Skip to content

Commit 5c1500b

Browse files
committed
test
1 parent fab55c4 commit 5c1500b

File tree

11 files changed

+169
-104
lines changed

11 files changed

+169
-104
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: 'Native Windows Bazel e2e test'
2+
description: 'Runs an Angular CLI e2e Bazel test on native Windows (dispatched from inside WSL)'
3+
author: 'Angular'
4+
5+
inputs:
6+
command:
7+
description: |
8+
Shell command to run the Bazel test. When multi-line, needs to end with
9+
a trailing `\` to allow for the extra added that enable running the
10+
WSL native Windows test.
11+
required: true
12+
13+
runs:
14+
using: composite
15+
steps:
16+
- name: Setup Bazel
17+
uses: angular/dev-infra/github-actions/bazel/setup@b015169b635123c1ab9084f604e36b6342eac171
18+
- name: Setup Bazel RBE
19+
uses: angular/dev-infra/github-actions/bazel/configure-remote@2667d139a421977a40c3ea7ec768609fb19a8b9d
20+
with:
21+
allow_windows_rbe: true
22+
23+
- name: Initialize WSL
24+
id: init_wsl
25+
uses: angular/dev-infra/github-actions/setup-wsl@0b004688d62e0fff2dbbb98362ff1b484348116a
26+
- name: Install node modules in WSL (re-using from previous install/cache restore)
27+
run: yarn install --immutable
28+
shell: wsl-bash {0}
29+
30+
# Notes for below command:
31+
# * strategy=TestRunner: Needed as we will create files outside of the WSL-bound sandbox.
32+
# * symlink_prefix=/: Needed as otherwise we will create unix symlinks in the Windows host.
33+
- run: |
34+
${{inputs.command}} \
35+
--//e2e/legacy-cli:enable_native_windows_testing=true \
36+
--test_env="NG_E2E_RUNNER_WSL_ROOT=${{steps.init_wsl.outputs.wsl_root_path}}" \
37+
--test_env="NG_E2E_RUNNER_WSL_UNC_BASE=${{steps.init_wsl.outputs.wsl_root_unc_path}}" \
38+
--test_env="NG_E2E_RUNNER_WINDOWS_CMD=${{steps.init_wsl.outputs.cmd_path}}" \
39+
--test_env="NG_E2E_RUNNER_WINDOWS_NPM=${{steps.init_wsl.outputs.npm_path}}" \
40+
--test_env="NG_E2E_RUNNER_WINDOWS_TMP_DIR=${{steps.init_wsl.outputs.tmp_path}}" \
41+
--test_env="NG_E2E_RUNNER_WINDOWS_GIT_BASH_BIN=${{steps.init_wsl.outputs.git_path}}" \
42+
--test_env="NG_E2E_RUNNER_WSL_HOST_ADDR=$(ip route show | grep -i default | awk '{ print $3}')" \
43+
--test_env="NG_E2E_RUNNER_WSL_VM_ADDR=$(hostname -I)" \
44+
--strategy=TestRunner=standalone \
45+
--symlink_prefix=/
46+
shell: wsl-bash {0}
47+
env:
48+
# See: https://devblogs.microsoft.com/commandline/share-environment-vars-between-wsl-and-windows
49+
WSLENV: 'GOOGLE_APPLICATION_CREDENTIALS/p'

.github/workflows/pr.yml

Lines changed: 25 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -129,93 +129,35 @@ jobs:
129129
# needs: build
130130
runs-on: windows-latest
131131
steps:
132-
# Git checkout converts to CRLF by default. This causes the Aspect lock
133-
# files to differ. See: https://github.com/actions/checkout/issues/135.
134-
- run: |
135-
git config --system core.autocrlf false
136-
git config --system core.eol lf
137132
- name: Initialize environment
138-
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@b015169b635123c1ab9084f604e36b6342eac171
139-
- name: Install node modules
140-
run: yarn install --immutable
141-
- name: Setup Bazel
142-
uses: angular/dev-infra/github-actions/bazel/setup@b015169b635123c1ab9084f604e36b6342eac171
143-
- name: Setup Bazel RBE
144-
uses: angular/dev-infra/github-actions/bazel/configure-remote@a5e90c88a0fc012de199fe6f148c12b5476d6d1b
145-
146-
- name: Setup tmate session
147-
uses: mxschmitt/action-tmate@v3
148-
with:
149-
detached: true
150-
151-
- uses: Vampire/setup-wsl@v4
152-
with:
153-
wsl-conf: |
154-
[interop]
155-
appendWindowsPath=false
156-
wsl-shell-command: bash --login -euo pipefail
157-
additional-packages: |
158-
curl
159-
ca-certificates
160-
g++
161-
unzip
162-
zip
163-
git
164-
python3
165-
tar
166-
- name: Setup nvm
167-
shell: wsl-bash {0}
168-
run: |
169-
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash
170-
export NVM_DIR="$HOME/.nvm"
171-
# Note: Specify `--install` due to https://github.com/nvm-sh/nvm/issues/1985.
172-
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" --install
173-
- run: nvm install
174-
shell: wsl-bash {0}
175-
- run: npm install -g yarn@1
176-
shell: wsl-bash {0}
177-
- name: Install node modules in WSL (re-using from previous install/cache restore)
178-
run: yarn install --immutable
179-
shell: wsl-bash {0}
180-
- name: Determining paths for WSL usage
181-
id: wsl_paths
182-
run: |
183-
cmd_path=$(which cmd.exe)
184-
cmd_wsl_path=$(wsl exec wslpath -u $cmd_path)
185-
npm_path=$(which npm)
186-
npm_wls_path=$(wsl exec wslpath -u "$npm_path")
187-
tmp_dir_wsl_path=$(wsl exec wslpath -u "/tmp")
188-
189-
git_bin=$(which git)
190-
git_bin_wsl_path=$(wsl exec wslpath -u "$git_bin")
191-
192-
echo "cmd_path=$cmd_wsl_path" >> $GITHUB_OUTPUT
193-
echo "npm_path=$npm_wls_path" >> $GITHUB_OUTPUT
194-
echo "tmp_path=$tmp_dir_wsl_path" >> $GITHUB_OUTPUT
195-
echo "git_path=$git_bin_wsl_path" >> $GITHUB_OUTPUT
196-
- name: Create link to WSL drive
197-
shell: powershell
198-
run: New-Item -ItemType SymbolicLink -Path "C:\wsl_root" -Target "\\wsl.localhost\Debian"
133+
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@d16848fd2ed19fce59488b540fa26a3353c72ad4
199134
- name: Run CLI E2E tests
200-
env:
201-
# See: https://devblogs.microsoft.com/commandline/share-environment-vars-between-wsl-and-windows
202-
WSLENV: 'GOOGLE_APPLICATION_CREDENTIALS/p'
203-
run: |
204-
yarn bazel test \
205-
--config=e2e //tests/legacy-cli:e2e_node22 \
135+
uses: ./.github/shared-actions/windows-bazel-test
136+
with:
137+
command: |
138+
yarn bazel test --config=e2e //tests/legacy-cli:e2e_node22 \
206139
--test_filter="tests/basic/{build,rebuild}.ts" \
207140
--test_arg="--esbuild" \
208-
--test_env="NG_E2E_RUNNER_WSL_ROOT=C:\wsl_root" \
209-
--test_env="NG_E2E_RUNNER_WSL_UNC_BASE=\\\\wsl.localhost\Debian" \
210-
--test_env="NG_E2E_RUNNER_WINDOWS_CMD=${{steps.wsl_paths.outputs.cmd_path}}" \
211-
--test_env="NG_E2E_RUNNER_WINDOWS_NPM=${{steps.wsl_paths.outputs.npm_path}}" \
212-
--test_env="NG_E2E_RUNNER_WINDOWS_TMP_DIR=${{steps.wsl_paths.outputs.tmp_path}}" \
213-
--test_env="NG_E2E_RUNNER_WINDOWS_GIT_BASH_BIN=${{steps.wsl_paths.outputs.git_path}}" \
214-
--test_env="NG_E2E_RUNNER_WSL_HOST_ADDR=$(ip route show | grep -i default | awk '{ print $3}')" \
215-
--test_env="NG_E2E_RUNNER_WSL_VM_ADDR=$(hostname -I)" \
216-
--test_output=streamed \
217-
--strategy=TestRunner=standalone
218-
shell: wsl-bash {0}
141+
142+
e2e_windows:
143+
strategy:
144+
fail-fast: false
145+
matrix:
146+
os: [windows-latest]
147+
node: [22]
148+
subset: [npm, esbuild]
149+
shard: [0, 1, 2, 3, 4, 5]
150+
runs-on: ${{ matrix.os }}
151+
steps:
152+
- name: Initialize environment
153+
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@d16848fd2ed19fce59488b540fa26a3353c72ad4
154+
- name: Run CLI E2E tests
155+
uses: ./.github/shared-actions/windows-bazel-test
156+
with:
157+
command: |
158+
yarn bazel test \
159+
--define=E2E_SHARD_TOTAL=6 --define=E2E_SHARD_INDEX=${{ matrix.shard }} \
160+
--config=e2e //tests/legacy-cli:e2e.${{ matrix.subset }}_node${{ matrix.node }} \
219161
220162
e2e-package-managers:
221163
needs: build

tests/legacy-cli/BUILD.bazel

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
1+
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
12
load("//tools:interop.bzl", "ts_project")
23
load(":e2e.bzl", "e2e_suites")
34

5+
bool_flag(
6+
name = "enable_native_windows_testing",
7+
build_setting_default = False,
8+
)
9+
10+
config_setting(
11+
name = "native_windows_testing",
12+
flag_values = {
13+
":enable_native_windows_testing": "true",
14+
},
15+
)
16+
417
ts_project(
518
name = "runner",
619
testonly = True,

tests/legacy-cli/e2e.bzl

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def e2e_suites(name, runner, data):
9494
# Saucelabs tests are only run on the default toolchain
9595
_e2e_suite(name, runner, "saucelabs", data)
9696

97-
def _e2e_tests(name, runner, **kwargs):
97+
def _e2e_tests(name, runner, windows_node_repo, **kwargs):
9898
# Always specify all the npm packages
9999
args = kwargs.pop("templated_args", []) + [
100100
"--package $(rootpath %s)" % p
@@ -126,17 +126,24 @@ def _e2e_tests(name, runner, **kwargs):
126126
toolchains = toolchains + ["@npm//@angular/build-tooling/bazel/browsers/chromium:toolchain_alias"]
127127
data = data + ["@npm//@angular/build-tooling/bazel/browsers/chromium"]
128128

129-
windows_node_repo = kwargs.pop("windows_node_repo", None)
130129
windows_node_files = [
131130
"@%s//:node_files" % windows_node_repo,
132131
"@%s//:npm_files" % windows_node_repo,
133132
"@%s//:bin/npm.cmd" % windows_node_repo,
134133
]
135134

135+
# In Windows native testing mode, add Windows dependencies. Those are not
136+
# available by default as we technically execute inside Linux/WSL.
137+
toolchains = select({
138+
"//e2e/legacy-cli:native_windows_testing": toolchains + [
139+
"@org_chromium_chromedriver_windows//:metadata",
140+
"@org_chromium_chromium_windows//:metadata",
141+
],
142+
"//conditions:default": toolchains,
143+
})
136144
data = select({
137-
"@bazel_tools//src/conditions:windows": data + windows_node_files,
138-
"//conditions:default": data + windows_node_files,
139-
#"//conditions:default": data,
145+
"//e2e/legacy-cli:native_windows_testing": data + windows_node_files,
146+
"//conditions:default": data,
140147
})
141148

142149
env.update({

tests/legacy-cli/e2e/initialize/300-log-environment.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ export default async function () {
1616
});
1717

1818
// On Windows, `which` might not be available.
19-
if (!isWindowsTestMode()) {
19+
if (isWindowsTestMode()) {
20+
console.log(
21+
`Skipping "$(which ng ${getActivePackageManager})" on Windows ` +
22+
`as the command may not be available.`,
23+
);
24+
} else {
2025
await exec('which', 'ng', getActivePackageManager());
2126
}
2227

tests/legacy-cli/e2e/setup/010-local-publish.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,10 @@ export default async function () {
1919
// Publish packages specified with --package
2020
await Promise.all(
2121
packageTars.map(({ path: p }) =>
22-
fetch(testRegistry).then(() =>
23-
globalNpm(['publish', '--tag', isPrereleaseCli() ? 'next' : 'latest', p], {
24-
...extractNpmEnv(),
25-
'NPM_CONFIG_USERCONFIG': npmrc,
26-
}),
27-
),
22+
globalNpm(['publish', '--tag', isPrereleaseCli() ? 'next' : 'latest', p], {
23+
...extractNpmEnv(),
24+
'NPM_CONFIG_USERCONFIG': npmrc,
25+
}),
2826
),
2927
);
3028
}

tests/legacy-cli/e2e/setup/100-global-cli.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ export default async function () {
2121
// Install global Angular CLI being tested, npm+yarn used by e2e tests.
2222
await globalNpm([
2323
'install',
24-
'-verbose',
2524
'--global',
2625
`--registry=${testRegistry}`,
2726
'@angular/cli',

tests/legacy-cli/e2e/utils/process.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ function _exec(options: ExecOptions, cmd: string, args: string[]): Promise<Proce
4545
// https://docs.npmjs.com/cli/v8/configuring-npm/folders#executables.
4646
// On Linux, macOS platforms, `bin/` is needed.
4747
const paths = [
48-
join(getGlobalVariable('yarn-global'), windowsMode !== null ? '' : 'bin'),
49-
join(getGlobalVariable('npm-global'), windowsMode !== null ? '' : 'bin'),
48+
join(getGlobalVariable('yarn-global'), windowsMode === null ? 'bin' : ''),
49+
join(getGlobalVariable('npm-global'), windowsMode === null ? 'bin' : ''),
5050
env.PATH || process.env['PATH'],
5151
].join(delimiter);
5252

tests/legacy-cli/e2e/utils/registry.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ export async function createNpmRegistry(
2525
for await (const events of on(verdaccioServer, 'message', {
2626
signal: AbortSignal.timeout(30_000),
2727
})) {
28-
console.log('VER:', events);
2928
if (
3029
events.some(
3130
(event: unknown) =>

tests/legacy-cli/e2e/utils/wsl.ts

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ import path from 'node:path';
44
import child_process from 'node:child_process';
55
import { getGlobalVariable } from './env';
66

7+
/** Cached Windows test mode value, avoiding recomputation. */
8+
let _cachedWindowsTestMode: WindowsWslTestMode | null | undefined = undefined;
9+
10+
/**
11+
* Type describing an object that will hold all relevant information
12+
* for supporting native Windows testing through WSL.
13+
*/
714
interface WindowsWslTestMode {
815
cmdPath: string;
916
gitBinaryDirForWindows: string;
@@ -12,14 +19,28 @@ interface WindowsWslTestMode {
1219
npmBinaryForWindowsPath: string;
1320
wslRootPath: string;
1421
wslUncBase: string;
22+
windowsChromedriverPath: string;
23+
windowsChromiumPath: string;
1524
}
1625

26+
/**
27+
* Path to a temporary directory inside the Windows host file system.
28+
* e.g. `/mnt/c/Users/runner/AppData/Local/Temp`
29+
*/
1730
export const windowsTmpDir = process.env['NG_E2E_RUNNER_WINDOWS_TMP_DIR'];
1831

32+
/**
33+
* Whether the given path needs to be translated to a Windows native path,
34+
* using `wslpath -w`. This is useful when detecting paths in CLI arguments.
35+
*/
1936
export function shouldInteropWslPath(p: string): boolean {
2037
return p.startsWith('/') && fs.existsSync(p);
2138
}
2239

40+
/**
41+
* Translates the given Unix WSL path into a Windows host system path, if
42+
* necessary, decided via {@link shouldInteropWslPath}.
43+
*/
2344
export function interopWslPathForOutsideIfNecessary(p: string): string {
2445
const windowsMode = isWindowsTestMode();
2546
assert(windowsMode !== null);
@@ -38,9 +59,20 @@ export function interopWslPathForOutsideIfNecessary(p: string): string {
3859
return p;
3960
}
4061

62+
/**
63+
* Gets whether we are currently testing native Windows.
64+
*
65+
* If so, returns an object exposing relevant information for
66+
* supporting such testing mode,
67+
*/
4168
export function isWindowsTestMode(): WindowsWslTestMode | null {
69+
if (_cachedWindowsTestMode !== undefined) {
70+
return _cachedWindowsTestMode;
71+
}
72+
4273
const cmdEnv = process.env['NG_E2E_RUNNER_WINDOWS_CMD'];
4374
if (cmdEnv === undefined) {
75+
_cachedWindowsTestMode = null;
4476
return null;
4577
}
4678

@@ -67,7 +99,7 @@ export function isWindowsTestMode(): WindowsWslTestMode | null {
6799
'bin/nodejs',
68100
);
69101

70-
return {
102+
return (_cachedWindowsTestMode = {
71103
cmdPath: cmdEnv,
72104
gitBinaryDirForWindows: path.dirname(gitBinaryForWindows),
73105
// We will copy the Node version outside of WSL because NPM might
@@ -76,13 +108,29 @@ export function isWindowsTestMode(): WindowsWslTestMode | null {
76108
nodeBinaryForWindowsPath: path.join(npmDir, 'node.exe'),
77109
nodeBinaryForWindowsInsideWslPath: path.resolve(nodeRepositoryDir, 'node.exe'),
78110
npmBinaryForWindowsPath: windowsNpmBin,
111+
windowsChromedriverPath: path.resolve(
112+
bazelTestWorkingDir,
113+
`../org_chromium_chromedriver_windows/chromedriver_win32/chromedriver.exe`,
114+
),
115+
windowsChromiumPath: path.resolve(
116+
bazelTestWorkingDir,
117+
`../org_chromium_chromium_windows/chrome-win/chrome.exe`,
118+
),
79119
wslRootPath,
80120
wslUncBase,
81-
};
121+
});
82122
}
83123

84124
/**
125+
* Takes the given process environment and computes a `WSLENV` environment
126+
* variable value that allows for the process environment to be usable
127+
* within the Windows host environment (e.g. in `cmd.exe`).
128+
*
129+
* By default, WSL does not inherit process environment variables, unless
130+
* explicitly specified via the `WSLENV` variable; which is also smart enough
131+
* to automatically translate paths of environment variables from Unix to Windows.
85132
*
133+
* See: https://devblogs.microsoft.com/commandline/share-environment-vars-between-wsl-and-windows/
86134
*/
87135
export function createWslEnv(env: NodeJS.ProcessEnv): string {
88136
const result: string[] = [];

0 commit comments

Comments
 (0)