fix(dev-infra): verify python3 is available before release (#41753)
Verify that the /usr/bin/python points to the python3 interpreter binary. PR Close #41753
This commit is contained in:
parent
8bfd9e886b
commit
a4a55f0687
|
@ -5179,7 +5179,7 @@ const ReleaseBuildCommandModule = {
|
|||
* output is captured and returned as resolution on completion. Depending on the chosen
|
||||
* output mode, stdout/stderr output is also printed to the console, or only on error.
|
||||
*
|
||||
* @returns a Promise resolving with captured stdout on success. The promise
|
||||
* @returns a Promise resolving with captured stdout and stderr on success. The promise
|
||||
* rejects on command failure.
|
||||
*/
|
||||
function spawnWithDebugOutput(command, args, options) {
|
||||
|
@ -5191,9 +5191,11 @@ function spawnWithDebugOutput(command, args, options) {
|
|||
var childProcess = child_process.spawn(command, args, tslib.__assign(tslib.__assign({}, options), { shell: true, stdio: ['inherit', 'pipe', 'pipe'] }));
|
||||
var logOutput = '';
|
||||
var stdout = '';
|
||||
var stderr = '';
|
||||
// Capture the stdout separately so that it can be passed as resolve value.
|
||||
// This is useful if commands return parsable stdout.
|
||||
childProcess.stderr.on('data', function (message) {
|
||||
stderr += message;
|
||||
logOutput += message;
|
||||
// If console output is enabled, print the message directly to the stderr. Note that
|
||||
// we intentionally print all output to stderr as stdout should not be polluted.
|
||||
|
@ -5218,7 +5220,7 @@ function spawnWithDebugOutput(command, args, options) {
|
|||
// On success, resolve the promise. Otherwise reject with the captured stderr
|
||||
// and stdout log output if the output mode was set to `silent`.
|
||||
if (status === 0) {
|
||||
resolve({ stdout: stdout });
|
||||
resolve({ stdout: stdout, stderr: stderr });
|
||||
}
|
||||
else {
|
||||
reject(outputMode === 'silent' ? logOutput : undefined);
|
||||
|
@ -6636,7 +6638,8 @@ class ReleaseTool {
|
|||
log(yellow(' Angular Dev-Infra release staging script'));
|
||||
log(yellow('--------------------------------------------'));
|
||||
log();
|
||||
if (!(yield this._verifyNoUncommittedChanges()) || !(yield this._verifyRunningFromNextBranch())) {
|
||||
if (!(yield this._verifyEnvironmentHasPython3Symlink()) ||
|
||||
!(yield this._verifyNoUncommittedChanges()) || !(yield this._verifyRunningFromNextBranch())) {
|
||||
return CompletionState.FATAL_ERROR;
|
||||
}
|
||||
if (!(yield this._verifyNpmLoginState())) {
|
||||
|
@ -6712,6 +6715,39 @@ class ReleaseTool {
|
|||
return true;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Verifies the current environment contains /usr/bin/python which points to the Python3
|
||||
* interpreter. python is required by our tooling in bazel as it contains scripts setting
|
||||
* `#! /usr/bin/env python`.
|
||||
*
|
||||
* @returns a boolean indicating success or failure.
|
||||
*/
|
||||
_verifyEnvironmentHasPython3Symlink() {
|
||||
return tslib.__awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
const pyVersion = yield spawnWithDebugOutput('/usr/bin/python', ['--version'], { mode: 'silent' });
|
||||
const version = pyVersion.stdout.trim() || pyVersion.stderr.trim();
|
||||
if (version.startsWith('Python 3.')) {
|
||||
debug(`Local python version: ${version}`);
|
||||
return true;
|
||||
}
|
||||
error(red(` ✘ \`/usr/bin/python\` is currently symlinked to "${version}", please update`));
|
||||
error(red(' the symlink to link instead to Python3'));
|
||||
error();
|
||||
error(red(' Googlers: please run the following command to symlink python to python3:'));
|
||||
error(red(' sudo ln -s /usr/bin/python3 /usr/bin/python'));
|
||||
return false;
|
||||
}
|
||||
catch (_a) {
|
||||
error(red(' ✘ `/usr/bin/python` does not exist, please ensure `/usr/bin/python` is'));
|
||||
error(red(' symlinked to Python3.'));
|
||||
error();
|
||||
error(red(' Googlers: please run the following command to symlink python to python3:'));
|
||||
error(red(' sudo ln -s /usr/bin/python3 /usr/bin/python'));
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Verifies that the next branch from the configured repository is checked out.
|
||||
* @returns a boolean indicating success or failure.
|
||||
|
|
|
@ -7,10 +7,12 @@
|
|||
*/
|
||||
|
||||
import {ListChoiceOptions, prompt} from 'inquirer';
|
||||
import {spawnWithDebugOutput} from '../../utils/child-process';
|
||||
|
||||
import {GithubConfig} from '../../utils/config';
|
||||
import {debug, error, info, log, promptConfirm, red, yellow} from '../../utils/console';
|
||||
import {GitClient} from '../../utils/git/index';
|
||||
import {exec} from '../../utils/shelljs';
|
||||
import {ReleaseConfig} from '../config/index';
|
||||
import {ActiveReleaseTrains, fetchActiveReleaseTrains, nextBranchName} from '../versioning/active-release-trains';
|
||||
import {npmIsLoggedIn, npmLogin, npmLogout} from '../versioning/npm-publish';
|
||||
|
@ -45,7 +47,8 @@ export class ReleaseTool {
|
|||
log(yellow('--------------------------------------------'));
|
||||
log();
|
||||
|
||||
if (!await this._verifyNoUncommittedChanges() || !await this._verifyRunningFromNextBranch()) {
|
||||
if (!await this._verifyEnvironmentHasPython3Symlink() ||
|
||||
!await this._verifyNoUncommittedChanges() || !await this._verifyRunningFromNextBranch()) {
|
||||
return CompletionState.FATAL_ERROR;
|
||||
}
|
||||
|
||||
|
@ -127,6 +130,38 @@ export class ReleaseTool {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the current environment contains /usr/bin/python which points to the Python3
|
||||
* interpreter. python is required by our tooling in bazel as it contains scripts setting
|
||||
* `#! /usr/bin/env python`.
|
||||
*
|
||||
* @returns a boolean indicating success or failure.
|
||||
*/
|
||||
private async _verifyEnvironmentHasPython3Symlink(): Promise<boolean> {
|
||||
try {
|
||||
const pyVersion =
|
||||
await spawnWithDebugOutput('/usr/bin/python', ['--version'], {mode: 'silent'});
|
||||
const version = pyVersion.stdout.trim() || pyVersion.stderr.trim();
|
||||
if (version.startsWith('Python 3.')) {
|
||||
debug(`Local python version: ${version}`);
|
||||
return true;
|
||||
}
|
||||
error(red(` ✘ \`/usr/bin/python\` is currently symlinked to "${version}", please update`));
|
||||
error(red(' the symlink to link instead to Python3'));
|
||||
error();
|
||||
error(red(' Googlers: please run the following command to symlink python to python3:'));
|
||||
error(red(' sudo ln -s /usr/bin/python3 /usr/bin/python'));
|
||||
return false;
|
||||
} catch {
|
||||
error(red(' ✘ `/usr/bin/python` does not exist, please ensure `/usr/bin/python` is'));
|
||||
error(red(' symlinked to Python3.'));
|
||||
error();
|
||||
error(red(' Googlers: please run the following command to symlink python to python3:'));
|
||||
error(red(' sudo ln -s /usr/bin/python3 /usr/bin/python'));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the next branch from the configured repository is checked out.
|
||||
* @returns a boolean indicating success or failure.
|
||||
|
|
|
@ -19,6 +19,8 @@ export interface SpawnedProcessOptions extends Omit<SpawnOptions, 'stdio'> {
|
|||
export interface SpawnedProcessResult {
|
||||
/** Captured stdout in string format. */
|
||||
stdout: string;
|
||||
/** Captured stderr in string format. */
|
||||
stderr: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,7 +28,7 @@ export interface SpawnedProcessResult {
|
|||
* output is captured and returned as resolution on completion. Depending on the chosen
|
||||
* output mode, stdout/stderr output is also printed to the console, or only on error.
|
||||
*
|
||||
* @returns a Promise resolving with captured stdout on success. The promise
|
||||
* @returns a Promise resolving with captured stdout and stderr on success. The promise
|
||||
* rejects on command failure.
|
||||
*/
|
||||
export function spawnWithDebugOutput(
|
||||
|
@ -42,10 +44,12 @@ export function spawnWithDebugOutput(
|
|||
spawn(command, args, {...options, shell: true, stdio: ['inherit', 'pipe', 'pipe']});
|
||||
let logOutput = '';
|
||||
let stdout = '';
|
||||
let stderr = '';
|
||||
|
||||
// Capture the stdout separately so that it can be passed as resolve value.
|
||||
// This is useful if commands return parsable stdout.
|
||||
childProcess.stderr.on('data', message => {
|
||||
stderr += message;
|
||||
logOutput += message;
|
||||
// If console output is enabled, print the message directly to the stderr. Note that
|
||||
// we intentionally print all output to stderr as stdout should not be polluted.
|
||||
|
@ -73,7 +77,7 @@ export function spawnWithDebugOutput(
|
|||
// On success, resolve the promise. Otherwise reject with the captured stderr
|
||||
// and stdout log output if the output mode was set to `silent`.
|
||||
if (status === 0) {
|
||||
resolve({stdout});
|
||||
resolve({stdout, stderr});
|
||||
} else {
|
||||
reject(outputMode === 'silent' ? logOutput : undefined);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue