Skip to content

Allow disabling SwiftPM sandboxing #1386

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 3 commits into from
Feb 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ default.profraw
assets/documentation-webview
assets/test/**/Package.resolved
assets/swift-docc-render
ud
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ node_modules/
/coverage/
/dist/
/snippets/

# macOS CI
/ud/
31 changes: 18 additions & 13 deletions .vscode-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,36 @@ const path = require("path");
const isCIBuild = process.env["CI"] === "1";
const isFastTestRun = process.env["FAST_TEST_RUN"] === "1";

const dataDir = process.env["VSCODE_DATA_DIR"];

// "env" in launch.json doesn't seem to work with vscode-test
const isDebugRun = !(process.env["_"] ?? "").endsWith("node_modules/.bin/vscode-test");

// so tests don't timeout when a breakpoint is hit
const timeout = isDebugRun ? Number.MAX_SAFE_INTEGER : 3000;

const launchArgs = [
"--disable-updates",
"--disable-crash-reporter",
"--disable-workspace-trust",
"--disable-telemetry",
];
if (dataDir) {
launchArgs.push("--user-data-dir", dataDir);
}
// GPU hardware acceleration not working on Darwin for intel
if (process.platform === "darwin" && process.arch === "x64") {
launchArgs.push("--disable-gpu");
}

module.exports = defineConfig({
tests: [
{
label: "integrationTests",
files: ["dist/test/common.js", "dist/test/integration-tests/**/*.test.js"],
version: process.env["VSCODE_VERSION"] ?? "stable",
workspaceFolder: "./assets/test",
launchArgs: [
"--disable-updates",
"--disable-crash-reporter",
"--disable-workspace-trust",
"--disable-telemetry",
],
launchArgs,
mocha: {
ui: "tdd",
color: true,
Expand All @@ -59,13 +70,7 @@ module.exports = defineConfig({
label: "unitTests",
files: ["dist/test/common.js", "dist/test/unit-tests/**/*.test.js"],
version: process.env["VSCODE_VERSION"] ?? "stable",
launchArgs: [
"--disable-extensions",
"--disable-updates",
"--disable-crash-reporter",
"--disable-workspace-trust",
"--disable-telemetry",
],
launchArgs: launchArgs.concat("--disable-extensions"),
mocha: {
ui: "tdd",
color: true,
Expand Down
1 change: 1 addition & 0 deletions assets/test/.vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"command": "command_plugin",
"args": ["--foo"],
"cwd": "command-plugin",
"disableSandbox": true,
"problemMatcher": [
"$swiftc"
],
Expand Down
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,12 @@
"swift.swiftSDK": {
"type": "string",
"default": "",
"markdownDescription": "The [Swift SDK](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0387-cross-compilation-destinations.md) to compile against (`--swift-sdk` parameter).",
"markdownDescription": "The [Swift SDK](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0387-cross-compilation-destinations.md) to compile against (`--swift-sdk` parameter)."
},
"swift.disableSandox": {
"type": "boolean",
"default": false,
"markdownDescription": "Disable sandboxing when running SwiftPM commands. In most cases you should keep the sandbox enabled and leave this setting set to `false`",
"order": 4
},
"swift.diagnostics": {
Expand Down
7 changes: 6 additions & 1 deletion src/commands/dependencies/unedit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,12 @@ async function uneditFolderDependency(
) {
try {
const uneditOperation = new SwiftExecOperation(
["package", "unedit", ...args, identifier],
ctx.toolchain.buildFlags.withAdditionalFlags([
"package",
"unedit",
...args,
identifier,
]),
folder,
`Finish editing ${identifier}`,
{ showStatusItem: true, checkAlreadyRunning: false, log: "Unedit" },
Expand Down
8 changes: 7 additions & 1 deletion src/commands/dependencies/useLocal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,13 @@ export async function useLocalDependency(
folder = folders[0];
}
const task = createSwiftTask(
["package", "edit", "--path", folder.fsPath, identifier],
ctx.toolchain.buildFlags.withAdditionalFlags([
"package",
"edit",
"--path",
folder.fsPath,
identifier,
]),
"Edit Package Dependency",
{
scope: currentFolder.workspaceFolder,
Expand Down
5 changes: 4 additions & 1 deletion src/commands/resetPackage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ export async function resetPackage(ctx: WorkspaceContext) {
*/
export async function folderResetPackage(folderContext: FolderContext) {
const task = createSwiftTask(
["package", "reset"],
folderContext.workspaceContext.toolchain.buildFlags.withAdditionalFlags([
"package",
"reset",
]),
"Reset Package Dependencies",
{
cwd: folderContext.folder,
Expand Down
11 changes: 11 additions & 0 deletions src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ export interface DebuggerConfiguration {
readonly debugAdapter: DebugAdapters;
/** Return path to debug adapter */
readonly customDebugAdapterPath: string;
/** Whether or not to disable setting up the debugger */
readonly disable: boolean;
}

/** workspace folder configuration */
Expand Down Expand Up @@ -212,6 +214,11 @@ const configuration = {
get customDebugAdapterPath(): string {
return vscode.workspace.getConfiguration("swift.debugger").get<string>("path", "");
},
get disable(): boolean {
return vscode.workspace
.getConfiguration("swift.debugger")
.get<boolean>("disable", false);
},
};
},
/** Files and directories to exclude from the code coverage. */
Expand Down Expand Up @@ -375,6 +382,10 @@ const configuration = {
.getConfiguration("swift")
.get<boolean>("enableTerminalEnvironment", true);
},
/** Whether or not to disable SwiftPM sandboxing */
get disableSandbox(): boolean {
return vscode.workspace.getConfiguration("swift").get<boolean>("disableSandbox", false);
},
};

export default configuration;
2 changes: 1 addition & 1 deletion src/debugger/buildConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ export class TestingConfigurationFactory {
}

const swiftTestingArgs = [
...args,
...this.ctx.workspaceContext.toolchain.buildFlags.withAdditionalFlags(args),
"--enable-swift-testing",
"--event-stream-version",
"0",
Expand Down
4 changes: 3 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,9 @@ export async function activate(context: vscode.ExtensionContext): Promise<Api> {
const workspaceContext = await WorkspaceContext.create(context, outputChannel, toolchain);
context.subscriptions.push(...commands.register(workspaceContext));
context.subscriptions.push(workspaceContext);
context.subscriptions.push(registerDebugger(workspaceContext));
if (!configuration.debugger.disable) {
context.subscriptions.push(registerDebugger(workspaceContext));
}
context.subscriptions.push(new SelectedXcodeWatcher(outputChannel));

// listen for workspace folder changes and active text editor changes
Expand Down
4 changes: 2 additions & 2 deletions src/tasks/SwiftPluginTaskProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export class SwiftPluginTaskProvider implements vscode.TaskProvider {
task.definition.command,
...task.definition.args,
];
swiftArgs = this.workspaceContext.toolchain.buildFlags.withSwiftSDKFlags(swiftArgs);
swiftArgs = this.workspaceContext.toolchain.buildFlags.withAdditionalFlags(swiftArgs);

const cwd = resolveTaskCwd(task, task.definition.cwd);
const newTask = new vscode.Task(
Expand Down Expand Up @@ -122,7 +122,7 @@ export class SwiftPluginTaskProvider implements vscode.TaskProvider {
plugin.command,
...definition.args,
];
swiftArgs = this.workspaceContext.toolchain.buildFlags.withSwiftSDKFlags(swiftArgs);
swiftArgs = this.workspaceContext.toolchain.buildFlags.withAdditionalFlags(swiftArgs);

const presentation = config?.presentationOptions ?? {};
const task = new vscode.Task(
Expand Down
5 changes: 3 additions & 2 deletions src/tasks/SwiftTaskProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ export function createSwiftTask(
cmdEnv: { [key: string]: string } = {}
): SwiftTask {
const swift = toolchain.getToolchainExecutable("swift");
args = toolchain.buildFlags.withSwiftPackageFlags(toolchain.buildFlags.withSwiftSDKFlags(args));
args = toolchain.buildFlags.withAdditionalFlags(args);

// Add relative path current working directory
const cwd = config.cwd.fsPath;
Expand Down Expand Up @@ -422,7 +422,8 @@ export class SwiftTaskProvider implements vscode.TaskProvider {
resolveTask(task: vscode.Task, token: vscode.CancellationToken): vscode.Task {
// We need to create a new Task object here.
// Reusing the task parameter doesn't seem to work.
const swift = this.workspaceContext.toolchain.getToolchainExecutable("swift");
const toolchain = this.workspaceContext.toolchain;
const swift = toolchain.getToolchainExecutable("swift");
// platform specific
let platform: TaskPlatformSpecificConfig | undefined;
if (process.platform === "win32") {
Expand Down
34 changes: 33 additions & 1 deletion src/toolchain/BuildFlags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class BuildFlags {
*
* @param args original commandline arguments
*/
withSwiftSDKFlags(args: string[]): string[] {
private withSwiftSDKFlags(args: string[]): string[] {
switch (args[0]) {
case "package": {
const subcommand = args.splice(0, 2).concat(this.buildPathFlags());
Expand Down Expand Up @@ -192,6 +192,38 @@ export class BuildFlags {
return indirect ? args.flatMap(arg => ["-Xswiftc", arg]) : args;
}

/**
* Get modified swift arguments with new arguments for disabling
* sandboxing if the `swift.disableSandbox` setting is enabled.
*
* @param args original commandline arguments
*/
private withDisableSandboxFlags(args: string[]): string[] {
if (!configuration.disableSandbox) {
return args;
}
const disableSandboxFlags = ["--disable-sandbox", "-Xswiftc", "-disable-sandbox"];
switch (args[0]) {
case "package": {
return [args[0], ...disableSandboxFlags, ...args.slice(1)];
}
case "build":
case "run":
case "test": {
return [...args, ...disableSandboxFlags];
}
default:
// Do nothing for other commands
return args;
}
}

withAdditionalFlags(args: string[]): string[] {
return this.withSwiftPackageFlags(
this.withDisableSandboxFlags(this.withSwiftSDKFlags(args))
);
}

/**
* Filter argument list
* @param args argument list
Expand Down
8 changes: 4 additions & 4 deletions src/utilities/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,14 @@ export async function execFile(
options.env = { ...(options.env ?? process.env), ...runtimeEnv };
}
}
return new Promise<{ stdout: string; stderr: string }>((resolve, reject) =>
return new Promise<{ stdout: string; stderr: string }>((resolve, reject) => {
cp.execFile(executable, args, options, (error, stdout, stderr) => {
if (error) {
reject(new ExecFileError(error, stdout, stderr));
}
resolve({ stdout, stderr });
})
);
});
});
}

export async function execFileStreamOutput(
Expand Down Expand Up @@ -187,7 +187,7 @@ export async function execSwift(
swift = toolchain.getToolchainExecutable("swift");
}
if (toolchain !== "default") {
args = toolchain.buildFlags.withSwiftSDKFlags(args);
args = toolchain.buildFlags.withAdditionalFlags(args);
}
if (Object.keys(configuration.swiftEnvironmentVariables).length > 0) {
// when adding environment vars we either combine with vars passed
Expand Down
2 changes: 1 addition & 1 deletion test/integration-tests/BackgroundCompilation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,5 @@ suite("BackgroundCompilation Test Suite", () => {
await vscode.workspace.save(uri);

await taskPromise;
}).timeout(120000);
}).timeout(180000);
});
6 changes: 3 additions & 3 deletions test/integration-tests/DiagnosticsManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ suite("DiagnosticsManager Test Suite", async function () {
// after first build and can cause intermittent
// failure if `swiftc` diagnostic is fixed
suiteSetup(async function () {
this.timeout(2 * 60 * 1000); // Allow 2 minutes to build
this.timeout(3 * 60 * 1000); // Allow 3 minutes to build
const task = createBuildAllTask(folderContext);
// This return exit code and output for the task but we will omit it here
// because the failures are expected and we just want the task to build
Expand Down Expand Up @@ -1062,7 +1062,7 @@ suite("DiagnosticsManager Test Suite", async function () {

assertHasDiagnostic(mainUri, expectedDiagnostic1);
assertHasDiagnostic(mainUri, expectedDiagnostic2);
}).timeout(2 * 60 * 1000); // Allow 2 minutes to build
}).timeout(3 * 60 * 1000); // Allow 3 minutes to build

test("Provides clang diagnostics", async () => {
// Build for indexing
Expand Down Expand Up @@ -1099,6 +1099,6 @@ suite("DiagnosticsManager Test Suite", async function () {

assertHasDiagnostic(cUri, expectedDiagnostic1);
assertHasDiagnostic(cUri, expectedDiagnostic2);
}).timeout(2 * 60 * 1000); // Allow 2 minutes to build
}).timeout(3 * 60 * 1000); // Allow 3 minutes to build
});
});
11 changes: 9 additions & 2 deletions test/integration-tests/SwiftPackage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,17 @@ suite("SwiftPackage Test Suite", () => {
assert.strictEqual(spmPackage.targets.length, 2);
}).timeout(10000);

test("Package resolve v2", async () => {
if (toolchain && toolchain.swiftVersion.isLessThan(new Version(5, 6, 0))) {
test("Package resolve v2", async function () {
if (!toolchain) {
return;
}
if (
(process.platform === "win32" &&
toolchain.swiftVersion.isLessThan(new Version(6, 0, 0))) ||
toolchain.swiftVersion.isLessThan(new Version(5, 6, 0))
) {
this.skip();
}
const spmPackage = await SwiftPackage.create(testAssetUri("package5.6"), toolchain);
assert.strictEqual(spmPackage.isValid, true);
assert(spmPackage.resolved !== undefined);
Expand Down
3 changes: 2 additions & 1 deletion test/integration-tests/SwiftSnippet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function normalizePath(...segments: string[]): string {
}

suite("SwiftSnippet Test Suite @slow", function () {
this.timeout(120000);
this.timeout(180000);

const uri = testAssetUri("defaultPackage/Snippets/hello.swift");
const breakpoints = [
Expand All @@ -62,6 +62,7 @@ suite("SwiftSnippet Test Suite @slow", function () {
// Set a breakpoint
vscode.debug.addBreakpoints(breakpoints);
},
requiresDebugger: true,
});

suiteTeardown(async () => {
Expand Down
3 changes: 2 additions & 1 deletion test/integration-tests/commands/build.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { Version } from "../../../src/utilities/version";

suite("Build Commands @slow", function () {
// Default timeout is a bit too short, give it a little bit more time
this.timeout(2 * 60 * 1000);
this.timeout(3 * 60 * 1000);

let folderContext: FolderContext;
let workspaceContext: WorkspaceContext;
Expand Down Expand Up @@ -56,6 +56,7 @@ suite("Build Commands @slow", function () {
async teardown() {
await vscode.commands.executeCommand(Workbench.ACTION_CLOSEALLEDITORS);
},
requiresDebugger: true,
});

test("Swift: Run Build", async () => {
Expand Down
1 change: 1 addition & 0 deletions test/integration-tests/debugger/lldb.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ suite("lldb contract test suite", () => {
}
workspaceContext = ctx;
},
requiresDebugger: true,
});

test("getLldbProcess Contract Test, make sure the command returns", async () => {
Expand Down
Loading