Skip to content

Commit

Permalink
Setup Windows GH actions job (#1195)
Browse files Browse the repository at this point in the history
* Setup Windows GH actions jobs

We cannot use the existing windows job setup because it launches a
docker container which we cannot open a VS Code window in to run
the tests as no tool like Xvfb exists for Windows

This patch goes through and fixes up tests and behaviours that were
incorrect on Windows.

Co-authored-by: Paul LeMarquand <[email protected]>
Co-authored-by: Michael (SPG) Weng <[email protected]>
  • Loading branch information
3 people authored Dec 3, 2024
1 parent e7f81c9 commit 3c116a4
Show file tree
Hide file tree
Showing 30 changed files with 571 additions and 319 deletions.
11 changes: 10 additions & 1 deletion .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ jobs:
name: Test
uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main
with:
# Linux
linux_exclude_swift_versions: '[{"swift_version": "nightly-main"}]'
linux_env_vars: |
NODE_VERSION=v18.19.0
Expand All @@ -23,7 +24,15 @@ jobs:
/bin/bash -c "source $NVM_DIR/nvm.sh && nvm install $NODE_VERSION"
echo "$NODE_PATH" >> $GITHUB_PATH
linux_build_command: ./docker/test.sh
enable_windows_checks: false
# Windows
windows_exclude_swift_versions: '[{"swift_version": "nightly"}]'
windows_env_vars: |
CI=1
VSCODE_TEST=1
FAST_TEST_RUN=1
windows_pre_build_command: .github\workflows\scripts\windows\install-nodejs.ps1
windows_build_command: docker\test-windows.ps1
enable_windows_docker: false

soundness:
name: Soundness
Expand Down
24 changes: 24 additions & 0 deletions .github/workflows/scripts/windows/install-nodejs.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
$NODEJS='https://nodejs.org/dist/v18.20.4/node-v18.20.4-x64.msi'
$NODEJS_SHA256='c2654d3557abd59de08474c6dd009b1d358f420b8e4010e4debbf130b1dfb90a'
Set-Variable ErrorActionPreference Stop
Set-Variable ProgressPreference SilentlyContinue
Write-Host -NoNewLine ('Downloading {0} ... ' -f ${NODEJS})
Invoke-WebRequest -Uri ${NODEJS} -OutFile $env:TEMP\node.msi
Write-Host 'SUCCESS'
Write-Host -NoNewLine ('Verifying SHA256 ({0}) ... ' -f ${NODEJS_SHA256})
$Hash = Get-FileHash $env:TEMP\node.msi -Algorithm sha256
if ($Hash.Hash -eq ${NODEJS_SHA256}) {
Write-Host 'SUCCESS'
} else {
Write-Host ('FAILED ({0})' -f $Hash.Hash)
exit 1
}
Write-Host -NoNewLine 'Installing node.js for Windows ... '
$Process = Start-Process msiexec "/i $env:TEMP\node.msi /norestart /qn" -Wait -PassThru
if ($Process.ExitCode -eq 0) {
Write-Host 'SUCCESS'
} else {
Write-Host ('FAILED ({0})' -f $Process.ExitCode)
exit 1
}
Remove-Item -Force $env:TEMP\node.msi
1 change: 1 addition & 0 deletions .vscode-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ module.exports = defineConfig({
},
},
reuseMachineInstall: !isCIBuild,
installExtensions: ["vadimcn.vscode-lldb"],
},
{
label: "unitTests",
Expand Down
13 changes: 13 additions & 0 deletions docker/test-windows.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
$env:CI = "1"
$env:FAST_TEST_RUN = "1"
npm ci -ignore-script node-pty
npm run lint
npm run format
npm run package
$Process = Start-Process npm "run integration-test" -Wait -PassThru -NoNewWindow
if ($Process.ExitCode -eq 0) {
Write-Host 'SUCCESS'
} else {
Write-Host ('FAILED ({0})' -f $Process.ExitCode)
exit 1
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1280,7 +1280,7 @@
"pretest": "npm run compile-tests",
"soundness": "docker compose -f docker/docker-compose.yaml -p swift-vscode-soundness-prb run --rm soundness",
"test-soundness": "scripts/soundness.sh",
"test": "VSCODE_TEST=1 vscode-test",
"test": "vscode-test",
"test-ci": "docker/test-ci.sh ci",
"test-nightly": "docker/test-ci.sh nightly",
"integration-test": "npm test -- --label integrationTests",
Expand Down
6 changes: 3 additions & 3 deletions src/DiagnosticsManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,13 @@ export class DiagnosticsManager implements vscode.Disposable {
.then(map => {
// Clean up old "swiftc" diagnostics
this.removeSwiftcDiagnostics();
map.forEach((diagnostics, uri) =>
map.forEach((diagnostics, uri) => {
this.handleDiagnostics(
vscode.Uri.file(uri),
DiagnosticsManager.isSwiftc,
diagnostics
)
);
);
});
})
.catch(e =>
context.outputChannel.log(`${e}`, 'Failed to provide "swiftc" diagnostics')
Expand Down
5 changes: 4 additions & 1 deletion src/FolderContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,10 @@ export class FolderContext implements vscode.Disposable {

/** Create Test explorer for this folder */
addTestExplorer() {
this.testExplorer = new TestExplorer(this);
if (this.testExplorer === undefined) {
this.testExplorer = new TestExplorer(this);
}
return this.testExplorer;
}

/** Create Test explorer for this folder */
Expand Down
7 changes: 6 additions & 1 deletion src/TestExplorer/TestParsers/XCTestOutputParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import { ITestRunState, TestIssueDiff } from "./TestRunState";
import { sourceLocationToVSCodeLocation } from "../../utilities/utilities";
import { MarkdownString, Location } from "vscode";
// eslint-disable-next-line @typescript-eslint/no-require-imports
import stripAnsi = require("strip-ansi");

/** Regex for parsing XCTest output */
interface TestRegex {
Expand Down Expand Up @@ -148,7 +150,10 @@ export class XCTestOutputParser implements IXCTestOutputParser {
* Parse results from `swift test` and update tests accordingly
* @param output Output from `swift test`
*/
public parseResult(output: string, runState: ITestRunState) {
public parseResult(rawOutput: string, runState: ITestRunState) {
// Windows is inserting ANSI codes into the output to do things like clear the cursor,
// which we don't care about.
const output = process.platform === "win32" ? stripAnsi(rawOutput) : rawOutput;
const output2 = output.replace(/\r\n/g, "\n");
const lines = output2.split("\n");
if (runState.excess) {
Expand Down
4 changes: 3 additions & 1 deletion src/TestExplorer/TestRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ import { BuildConfigurationFactory, TestingConfigurationFactory } from "../debug
import { TestKind, isDebugging, isRelease } from "./TestKind";
import { reduceTestItemChildren } from "./TestUtils";
import { CompositeCancellationToken } from "../utilities/cancellation";
// eslint-disable-next-line @typescript-eslint/no-require-imports
import stripAnsi = require("strip-ansi");

export enum TestLibrary {
xctest = "XCTest",
Expand Down Expand Up @@ -264,7 +266,7 @@ export class TestRunProxy {
test?: vscode.TestItem
) {
testRun.appendOutput(output, location, test);
this.runState.output.push(output);
this.runState.output.push(stripAnsi(output));
}

private prependIterationToOutput(output: string): string {
Expand Down
14 changes: 13 additions & 1 deletion src/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,28 @@ export async function debugBuildWithOptions(
) {
const current = ctx.currentFolder;
if (!current) {
ctx.outputChannel.appendLine(
"debugBuildWithOptions: No current folder on WorkspaceContext"
);
return;
}

const file = vscode.window.activeTextEditor?.document.fileName;
if (!file) {
ctx.outputChannel.appendLine("debugBuildWithOptions: No active text editor");
return;
}

const target = current.swiftPackage.getTarget(file);
if (!target || target.type !== "executable") {
if (!target) {
ctx.outputChannel.appendLine("debugBuildWithOptions: No active target");
return;
}

if (target.type !== "executable") {
ctx.outputChannel.appendLine(
`debugBuildWithOptions: Target is not an executable, instead is ${target.type}`
);
return;
}

Expand Down
14 changes: 12 additions & 2 deletions src/debugger/launch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,17 +113,27 @@ export function getLaunchConfiguration(
const wsLaunchSection = vscode.workspace.getConfiguration("launch", folderCtx.workspaceFolder);
const launchConfigs = wsLaunchSection.get<vscode.DebugConfiguration[]>("configurations") || [];
const { folder } = getFolderAndNameSuffix(folderCtx);
const buildDirectory = BuildFlags.buildDirectoryFromWorkspacePath(folder, true);
const targetPath = path.join(
BuildFlags.buildDirectoryFromWorkspacePath(folder, true),
"debug",
target
);
// Users could be on different platforms with different path annotations,
// so normalize before we compare.
return launchConfigs.find(
config => config.program === path.join(buildDirectory, "debug", target)
config => path.normalize(config.program) === path.normalize(targetPath)
);
}

// Return array of DebugConfigurations for executables based on what is in Package.swift
function createExecutableConfigurations(ctx: FolderContext): vscode.DebugConfiguration[] {
const executableProducts = ctx.swiftPackage.executableProducts;

// Windows understand the forward slashes, so make the configuration unified as posix path
// to make it easier for users switching between platforms.
const { folder, nameSuffix } = getFolderAndNameSuffix(ctx, undefined, "posix");
const buildDirectory = BuildFlags.buildDirectoryFromWorkspacePath(folder, true, "posix");

return executableProducts.flatMap(product => {
const baseConfig = {
type: DebugAdapter.getLaunchConfigType(ctx.workspaceContext.swiftVersion),
Expand Down
7 changes: 5 additions & 2 deletions src/debugger/lldb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,18 @@ export async function getLldbProcess(
"platform process list --show-args --all-users",
]);
const entries = stdout.split("\n");
return entries.flatMap(line => {
const processes = entries.flatMap(line => {
const match = /^(\d+)\s+\d+\s+\S+\s+\S+\s+(.+)$/.exec(line);
if (match) {
return [{ pid: parseInt(match[1]), label: `${match[1]}: ${match[2]}` }];
} else {
return [];
}
});
return processes;
} catch (error) {
vscode.window.showErrorMessage(`Failed to run LLDB: ${getErrorDescription(error)}`);
const errorMessage = `Failed to run LLDB: ${getErrorDescription(error)}`;
ctx.outputChannel.log(errorMessage);
vscode.window.showErrorMessage(errorMessage);
}
}
2 changes: 1 addition & 1 deletion src/tasks/SwiftProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export class SwiftPtyProcess implements SwiftProcess {
useConpty,
// https://github.com/swiftlang/vscode-swift/issues/1074
// Causing weird truncation issues
cols: !isWindows || useConpty ? undefined : 2147483647, // Max int32
cols: isWindows ? 4096 : undefined,
});
this.spawnEmitter.fire();
this.spawnedProcess.onData(data => {
Expand Down
1 change: 1 addition & 0 deletions src/toolchain/toolchain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@ export class SwiftToolchain {
get diagnostics(): string {
let str = "";
str += this.swiftVersionString;
str += `\nPlatform: ${process.platform}`;
str += `\nSwift Path: ${this.swiftFolderPath}`;
str += `\nToolchain Path: ${this.toolchainPath}`;
if (this.runtimePath) {
Expand Down
9 changes: 2 additions & 7 deletions src/ui/SwiftOutputChannel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,10 @@ export class SwiftOutputChannel implements vscode.OutputChannel {
}

logDiagnostic(message: string, label?: string) {
if (!configuration.diagnostics) {
if (!configuration.diagnostics && process.env["CI"] !== "1") {
return;
}
let fullMessage: string;
if (label !== undefined) {
fullMessage = `${label}: ${message}`;
} else {
fullMessage = message;
}
const fullMessage = label !== undefined ? `${label}: ${message}` : message;
this.appendLine(`${this.nowFormatted}: ${fullMessage}`);
}

Expand Down
Loading

0 comments on commit 3c116a4

Please sign in to comment.