Skip to content
Open
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
82 changes: 82 additions & 0 deletions .github/workflows/package-manager-network-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Package Manager Network Check

on:
workflow_dispatch:

permissions:
contents: read

env:
NODE_VERSION: '22.21.1'

jobs:
package-manager-network-tests:
name: Package Manager Network Tests
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1

- name: Checkout Python Environment Tools
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
repository: 'microsoft/python-environment-tools'
path: 'python-env-tools-src'
sparse-checkout: |
crates
Cargo.toml
Cargo.lock
sparse-checkout-cone-mode: false

- name: Install Rust Toolchain
uses: dtolnay/rust-toolchain@stable

- name: Cache Rust build
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: |
~/.cargo/registry
~/.cargo/git
python-env-tools-src/target
key: ${{ runner.os }}-cargo-pet-${{ hashFiles('python-env-tools-src/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-pet-

- name: Build Python Environment Tools
run: cargo build --release --package pet
working-directory: python-env-tools-src

- name: Copy pet binary
run: |
mkdir -p python-env-tools/bin
cp python-env-tools-src/target/release/pet python-env-tools/bin/
chmod +x python-env-tools/bin/pet

- name: Install Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: Install Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'

- name: Install Dependencies
run: npm ci

- name: Compile Extension
run: npm run compile

- name: Compile Tests
run: npm run compile-tests

- name: Run Package Manager Network Integration Tests
uses: GabrielBB/xvfb-action@86d97bde4a65fe9b290c0b3fb92c2c4ed0e5302d # v1.6
env:
VSC_PYTHON_PACKAGE_NETWORK_TEST: '1'
with:
run: npm run integration-test -- --grep "Package Manager"
8 changes: 0 additions & 8 deletions .github/workflows/pr-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -335,14 +335,6 @@ jobs:
if: runner.os != 'Linux'
Comment thread
edvilme marked this conversation as resolved.
run: npm run integration-test

- name: Run Package Manager Network Integration Tests
if: runner.os == 'Linux' && matrix.python-version == '3.12'
uses: GabrielBB/xvfb-action@86d97bde4a65fe9b290c0b3fb92c2c4ed0e5302d # v1.6
env:
VSC_PYTHON_PACKAGE_NETWORK_TEST: '1'
with:
run: npm run integration-test -- --grep "Package Manager"

integration-tests-multiroot:
name: Integration Tests (Multi-Root)
runs-on: ${{ matrix.os }}
Expand Down
8 changes: 0 additions & 8 deletions .github/workflows/push-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -335,11 +335,3 @@ jobs:
- name: Run Integration Tests (non-Linux)
if: runner.os != 'Linux'
run: npm run integration-test

- name: Run Package Manager Network Integration Tests
if: runner.os == 'Linux' && matrix.python-version == '3.12'
uses: GabrielBB/xvfb-action@86d97bde4a65fe9b290c0b3fb92c2c4ed0e5302d # v1.6
env:
VSC_PYTHON_PACKAGE_NETWORK_TEST: '1'
with:
run: npm run integration-test -- --grep "Package Manager"
70 changes: 39 additions & 31 deletions src/managers/builtin/pipPackageManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import type { Pep440Version } from '@renovatebot/pep440';
import { compare, explain as parse, rcompare } from '@renovatebot/pep440';
import {
CancellationError,
CancellationToken,
Disposable,
Event,
EventEmitter,
LogOutputChannel,
MarkdownString,
ProgressLocation,
ThemeIcon,
window,
} from 'vscode';
import {
DidChangePackagesEventArgs,
Expand All @@ -21,6 +21,7 @@ import {
PythonEnvironment,
PythonEnvironmentApi,
} from '../../api';
import { showErrorMessage, withProgress } from '../../common/window.apis';
import { updatePackagesAndNotify } from '../common/packageChanges';
import { runPython, runUV, shouldUseUv } from './helpers';
import { getWorkspacePackagesToInstall } from './pipUtils';
Expand Down Expand Up @@ -74,45 +75,52 @@ export class PipPackageManager implements PackageManager, Disposable {
install: toInstall,
uninstall: toUninstall,
};
await window.withProgress(
const execute = async (token?: CancellationToken): Promise<void> => {
try {
await managePackages(environment, manageOptions, this, token);
await updatePackagesAndNotify(
this,
environment,
this.packages.get(environment.envId.id),
(changes) => {
this._onDidChangePackages.fire({ environment, manager: this, changes });
},
() => this.fetchPackages(environment, !manageOptions.runHeadless),
);
} catch (e) {
if (e instanceof CancellationError) {
throw e;
}
this.log.error('Error managing packages', e);
if (!manageOptions.runHeadless) {
setImmediate(async () => {
const result = await showErrorMessage('Error managing packages', 'View Output');
if (result === 'View Output') {
this.log.show();
}
});
}
throw e;
}
};

if (manageOptions.runHeadless) {
await execute();
return;
}

await withProgress(
{
location: ProgressLocation.Notification,
title: 'Installing packages',
cancellable: true,
},
async (_progress, token) => {
try {
await managePackages(environment, manageOptions, this, token);
await updatePackagesAndNotify(
this,
environment,
this.packages.get(environment.envId.id),
(changes) => {
this._onDidChangePackages.fire({ environment, manager: this, changes });
},
() => this.fetchPackages(environment, !manageOptions.runHeadless),
);
} catch (e) {
if (e instanceof CancellationError) {
throw e;
}
this.log.error('Error managing packages', e);
if (!manageOptions.runHeadless) {
setImmediate(async () => {
const result = await window.showErrorMessage('Error managing packages', 'View Output');
if (result === 'View Output') {
this.log.show();
}
});
}
throw e;
}
},
async (_progress, token) => execute(token),
);
}

async refresh(environment: PythonEnvironment): Promise<void> {
await window.withProgress(
await withProgress(
{
location: ProgressLocation.Window,
title: 'Refreshing packages',
Expand Down
58 changes: 33 additions & 25 deletions src/managers/conda/condaPackageManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { explain as parse, rcompare } from '@renovatebot/pep440';
import * as path from 'path';
import {
CancellationError,
CancellationToken,
Disposable,
Event,
EventEmitter,
Expand Down Expand Up @@ -72,37 +73,44 @@ export class CondaPackageManager implements PackageManager, Disposable {
install: toInstall,
uninstall: toUninstall,
};
const execute = async (token?: CancellationToken): Promise<void> => {
try {
await managePackages(environment, manageOptions, token, this.log);
await updatePackagesAndNotify(
this,
environment,
this.packages.get(environment.envId.id),
(changes) => {
this._onDidChangePackages.fire({ environment, manager: this, changes });
},
);
} catch (e) {
if (e instanceof CancellationError) {
throw e;
}

this.log.error('Error installing packages', e);
if (!manageOptions.runHeadless) {
setImmediate(async () => {
await showErrorMessageWithLogs(CondaStrings.condaInstallError, this.log);
});
}
throw e;
}
};

if (manageOptions.runHeadless) {
await execute();
return;
}

await withProgress(
{
location: ProgressLocation.Notification,
title: CondaStrings.condaInstallingPackages,
cancellable: true,
},
async (_progress, token) => {
try {
await managePackages(environment, manageOptions, token, this.log);
await updatePackagesAndNotify(
this,
environment,
this.packages.get(environment.envId.id),
(changes) => {
this._onDidChangePackages.fire({ environment, manager: this, changes });
},
);
} catch (e) {
if (e instanceof CancellationError) {
throw e;
}

this.log.error('Error installing packages', e);
if (!manageOptions.runHeadless) {
setImmediate(async () => {
await showErrorMessageWithLogs(CondaStrings.condaInstallError, this.log);
});
}
throw e;
}
},
async (_progress, token) => execute(token),
);
}

Expand Down
2 changes: 1 addition & 1 deletion src/managers/conda/condaUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1253,7 +1253,7 @@ export async function deleteCondaEnvironment(environment: PythonEnvironment, log
export async function managePackages(
environment: PythonEnvironment,
options: PackageManagementOptions,
token: CancellationToken,
token: CancellationToken | undefined,
log: LogOutputChannel,
): Promise<void> {
if (options.uninstall && options.uninstall.length > 0) {
Expand Down
61 changes: 34 additions & 27 deletions src/managers/poetry/poetryPackageManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,39 +81,46 @@ export class PoetryPackageManager implements PackageManager, Disposable {
}
}

const execute = async (token?: CancellationToken): Promise<void> => {
try {
await this.runPoetryManage({ install: toInstall, uninstall: toUninstall }, token);
await updatePackagesAndNotify(
this,
environment,
this.packages.get(environment.envId.id),
(changes) => {
this._onDidChangePackages.fire({ environment, manager: this, changes });
},
);
} catch (e) {
if (e instanceof CancellationError) {
throw e;
}
this.log.error('Error managing packages with Poetry', e);
if (!options.runHeadless) {
setImmediate(async () => {
const result = await showErrorMessage('Error managing packages with Poetry', 'View Output');
if (result === 'View Output') {
this.log.show();
}
});
}
throw e;
}
};

if (options.runHeadless) {
await execute();
return;
}

await withProgress(
{
location: ProgressLocation.Notification,
title: 'Managing packages with Poetry',
cancellable: true,
},
async (_progress, token) => {
try {
await this.runPoetryManage({ install: toInstall, uninstall: toUninstall }, token);
await updatePackagesAndNotify(
this,
environment,
this.packages.get(environment.envId.id),
(changes) => {
this._onDidChangePackages.fire({ environment, manager: this, changes });
},
);
} catch (e) {
if (e instanceof CancellationError) {
throw e;
}
this.log.error('Error managing packages with Poetry', e);
if (!options.runHeadless) {
setImmediate(async () => {
const result = await showErrorMessage('Error managing packages with Poetry', 'View Output');
if (result === 'View Output') {
this.log.show();
}
});
}
throw e;
}
},
async (_progress, token) => execute(token),
);
}

Expand Down
Loading
Loading