mirror of
https://github.com/actions/setup-python.git
synced 2025-12-24 17:27:09 +00:00
Add support for custom PyPI repository configuration
- Add pypi-url, pypi-username, and pypi-password inputs to action.yml - Implement configurePipRepository() function in utils.ts to create pip.conf/pip.ini - Integrate pip configuration into setup-python.ts workflow - Add comprehensive unit tests for pip configuration functionality - Update README.md with usage examples and documentation - Automatically mask credentials in logs for security Fixes #814
This commit is contained in:
parent
83679a892e
commit
f054be5a92
5 changed files with 222 additions and 2 deletions
|
|
@ -11,7 +11,8 @@ import {
|
|||
logWarning,
|
||||
IS_MAC,
|
||||
getVersionInputFromFile,
|
||||
getVersionsInputFromPlainFile
|
||||
getVersionsInputFromPlainFile,
|
||||
configurePipRepository
|
||||
} from './utils';
|
||||
import {exec} from '@actions/exec';
|
||||
|
||||
|
|
@ -159,6 +160,12 @@ async function run() {
|
|||
if (cache && isCacheFeatureAvailable()) {
|
||||
await cacheDependencies(cache, pythonVersion);
|
||||
}
|
||||
const pypiUrl = core.getInput('pypi-url');
|
||||
if (pypiUrl) {
|
||||
const pypiUsername = core.getInput('pypi-username');
|
||||
const pypiPassword = core.getInput('pypi-password');
|
||||
await configurePipRepository(pypiUrl, pypiUsername, pypiPassword);
|
||||
}
|
||||
const pipInstall = core.getInput('pip-install');
|
||||
if (pipInstall) {
|
||||
await installPipPackages(pipInstall);
|
||||
|
|
|
|||
73
src/utils.ts
73
src/utils.ts
|
|
@ -422,3 +422,76 @@ export function getDownloadFileName(downloadUrl: string): string | undefined {
|
|||
? path.join(tempDir, path.basename(downloadUrl))
|
||||
: undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure pip to use a custom PyPI repository
|
||||
* Creates a pip.conf (Linux/macOS) or pip.ini (Windows) file with repository and credentials
|
||||
* @param pypiUrl The custom PyPI repository URL
|
||||
* @param username The username for authentication (optional)
|
||||
* @param password The password or token for authentication (optional)
|
||||
*/
|
||||
export async function configurePipRepository(
|
||||
pypiUrl: string,
|
||||
username?: string,
|
||||
password?: string
|
||||
): Promise<void> {
|
||||
if (!pypiUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
core.info(`Configuring pip to use custom PyPI repository: ${pypiUrl}`);
|
||||
|
||||
// Determine the pip config file location and name based on OS
|
||||
const homeDir = process.env.HOME || process.env.USERPROFILE || '';
|
||||
const configDir = IS_WINDOWS
|
||||
? path.join(homeDir, 'pip')
|
||||
: path.join(homeDir, '.pip');
|
||||
const configFile = IS_WINDOWS ? 'pip.ini' : 'pip.conf';
|
||||
const configPath = path.join(configDir, configFile);
|
||||
|
||||
// Create the config directory if it doesn't exist
|
||||
if (!fs.existsSync(configDir)) {
|
||||
fs.mkdirSync(configDir, {recursive: true});
|
||||
}
|
||||
|
||||
// Build the index URL with credentials if provided
|
||||
let indexUrl = pypiUrl;
|
||||
if (username && password) {
|
||||
// Parse the URL to inject credentials
|
||||
try {
|
||||
const url = new URL(pypiUrl);
|
||||
url.username = encodeURIComponent(username);
|
||||
url.password = encodeURIComponent(password);
|
||||
indexUrl = url.toString();
|
||||
} catch (error) {
|
||||
core.warning(
|
||||
`Failed to parse PyPI URL: ${pypiUrl}. Using URL without credentials.`
|
||||
);
|
||||
indexUrl = pypiUrl;
|
||||
}
|
||||
} else if (username || password) {
|
||||
core.warning(
|
||||
'Both pypi-username and pypi-password must be provided for authentication. Configuring without credentials.'
|
||||
);
|
||||
}
|
||||
|
||||
// Create the pip config content
|
||||
const configContent = `[global]
|
||||
index-url = ${indexUrl}
|
||||
`;
|
||||
|
||||
// Write the config file
|
||||
try {
|
||||
fs.writeFileSync(configPath, configContent, {encoding: 'utf8'});
|
||||
core.info(`Successfully created pip config file at: ${configPath}`);
|
||||
|
||||
// Mask the password in logs if credentials were used
|
||||
if (password) {
|
||||
core.setSecret(password);
|
||||
}
|
||||
} catch (error) {
|
||||
core.setFailed(
|
||||
`Failed to create pip config file at ${configPath}: ${error}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue