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 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.
|
* 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.
|
* rejects on command failure.
|
||||||
*/
|
*/
|
||||||
function spawnWithDebugOutput(command, args, options) {
|
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 childProcess = child_process.spawn(command, args, tslib.__assign(tslib.__assign({}, options), { shell: true, stdio: ['inherit', 'pipe', 'pipe'] }));
|
||||||
var logOutput = '';
|
var logOutput = '';
|
||||||
var stdout = '';
|
var stdout = '';
|
||||||
|
var stderr = '';
|
||||||
// Capture the stdout separately so that it can be passed as resolve value.
|
// Capture the stdout separately so that it can be passed as resolve value.
|
||||||
// This is useful if commands return parsable stdout.
|
// This is useful if commands return parsable stdout.
|
||||||
childProcess.stderr.on('data', function (message) {
|
childProcess.stderr.on('data', function (message) {
|
||||||
|
stderr += message;
|
||||||
logOutput += message;
|
logOutput += message;
|
||||||
// If console output is enabled, print the message directly to the stderr. Note that
|
// 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.
|
// 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
|
// On success, resolve the promise. Otherwise reject with the captured stderr
|
||||||
// and stdout log output if the output mode was set to `silent`.
|
// and stdout log output if the output mode was set to `silent`.
|
||||||
if (status === 0) {
|
if (status === 0) {
|
||||||
resolve({ stdout: stdout });
|
resolve({ stdout: stdout, stderr: stderr });
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
reject(outputMode === 'silent' ? logOutput : undefined);
|
reject(outputMode === 'silent' ? logOutput : undefined);
|
||||||
|
@ -6636,7 +6638,8 @@ class ReleaseTool {
|
||||||
log(yellow(' Angular Dev-Infra release staging script'));
|
log(yellow(' Angular Dev-Infra release staging script'));
|
||||||
log(yellow('--------------------------------------------'));
|
log(yellow('--------------------------------------------'));
|
||||||
log();
|
log();
|
||||||
if (!(yield this._verifyNoUncommittedChanges()) || !(yield this._verifyRunningFromNextBranch())) {
|
if (!(yield this._verifyEnvironmentHasPython3Symlink()) ||
|
||||||
|
!(yield this._verifyNoUncommittedChanges()) || !(yield this._verifyRunningFromNextBranch())) {
|
||||||
return CompletionState.FATAL_ERROR;
|
return CompletionState.FATAL_ERROR;
|
||||||
}
|
}
|
||||||
if (!(yield this._verifyNpmLoginState())) {
|
if (!(yield this._verifyNpmLoginState())) {
|
||||||
|
@ -6712,6 +6715,39 @@ class ReleaseTool {
|
||||||
return true;
|
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.
|
* Verifies that the next branch from the configured repository is checked out.
|
||||||
* @returns a boolean indicating success or failure.
|
* @returns a boolean indicating success or failure.
|
||||||
|
|
|
@ -7,10 +7,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {ListChoiceOptions, prompt} from 'inquirer';
|
import {ListChoiceOptions, prompt} from 'inquirer';
|
||||||
|
import {spawnWithDebugOutput} from '../../utils/child-process';
|
||||||
|
|
||||||
import {GithubConfig} from '../../utils/config';
|
import {GithubConfig} from '../../utils/config';
|
||||||
import {debug, error, info, log, promptConfirm, red, yellow} from '../../utils/console';
|
import {debug, error, info, log, promptConfirm, red, yellow} from '../../utils/console';
|
||||||
import {GitClient} from '../../utils/git/index';
|
import {GitClient} from '../../utils/git/index';
|
||||||
|
import {exec} from '../../utils/shelljs';
|
||||||
import {ReleaseConfig} from '../config/index';
|
import {ReleaseConfig} from '../config/index';
|
||||||
import {ActiveReleaseTrains, fetchActiveReleaseTrains, nextBranchName} from '../versioning/active-release-trains';
|
import {ActiveReleaseTrains, fetchActiveReleaseTrains, nextBranchName} from '../versioning/active-release-trains';
|
||||||
import {npmIsLoggedIn, npmLogin, npmLogout} from '../versioning/npm-publish';
|
import {npmIsLoggedIn, npmLogin, npmLogout} from '../versioning/npm-publish';
|
||||||
|
@ -45,7 +47,8 @@ export class ReleaseTool {
|
||||||
log(yellow('--------------------------------------------'));
|
log(yellow('--------------------------------------------'));
|
||||||
log();
|
log();
|
||||||
|
|
||||||
if (!await this._verifyNoUncommittedChanges() || !await this._verifyRunningFromNextBranch()) {
|
if (!await this._verifyEnvironmentHasPython3Symlink() ||
|
||||||
|
!await this._verifyNoUncommittedChanges() || !await this._verifyRunningFromNextBranch()) {
|
||||||
return CompletionState.FATAL_ERROR;
|
return CompletionState.FATAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +130,38 @@ export class ReleaseTool {
|
||||||
return true;
|
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.
|
* Verifies that the next branch from the configured repository is checked out.
|
||||||
* @returns a boolean indicating success or failure.
|
* @returns a boolean indicating success or failure.
|
||||||
|
|
|
@ -19,6 +19,8 @@ export interface SpawnedProcessOptions extends Omit<SpawnOptions, 'stdio'> {
|
||||||
export interface SpawnedProcessResult {
|
export interface SpawnedProcessResult {
|
||||||
/** Captured stdout in string format. */
|
/** Captured stdout in string format. */
|
||||||
stdout: string;
|
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 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.
|
* 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.
|
* rejects on command failure.
|
||||||
*/
|
*/
|
||||||
export function spawnWithDebugOutput(
|
export function spawnWithDebugOutput(
|
||||||
|
@ -42,10 +44,12 @@ export function spawnWithDebugOutput(
|
||||||
spawn(command, args, {...options, shell: true, stdio: ['inherit', 'pipe', 'pipe']});
|
spawn(command, args, {...options, shell: true, stdio: ['inherit', 'pipe', 'pipe']});
|
||||||
let logOutput = '';
|
let logOutput = '';
|
||||||
let stdout = '';
|
let stdout = '';
|
||||||
|
let stderr = '';
|
||||||
|
|
||||||
// Capture the stdout separately so that it can be passed as resolve value.
|
// Capture the stdout separately so that it can be passed as resolve value.
|
||||||
// This is useful if commands return parsable stdout.
|
// This is useful if commands return parsable stdout.
|
||||||
childProcess.stderr.on('data', message => {
|
childProcess.stderr.on('data', message => {
|
||||||
|
stderr += message;
|
||||||
logOutput += message;
|
logOutput += message;
|
||||||
// If console output is enabled, print the message directly to the stderr. Note that
|
// 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.
|
// 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
|
// On success, resolve the promise. Otherwise reject with the captured stderr
|
||||||
// and stdout log output if the output mode was set to `silent`.
|
// and stdout log output if the output mode was set to `silent`.
|
||||||
if (status === 0) {
|
if (status === 0) {
|
||||||
resolve({stdout});
|
resolve({stdout, stderr});
|
||||||
} else {
|
} else {
|
||||||
reject(outputMode === 'silent' ? logOutput : undefined);
|
reject(outputMode === 'silent' ? logOutput : undefined);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue