зеркало из https://github.com/Azure/powershell.git
support MacOS and self-hosted runner (#91)
This commit is contained in:
Родитель
1dcd677e09
Коммит
7f8525f92c
|
@ -56,37 +56,6 @@ describe("Testing AzModuleInstaller", () => {
|
|||
expect(spyTryInstallingLatest).toBeCalledTimes(1);
|
||||
expect(mockTryInstalledTrue).toBeCalledTimes(4);
|
||||
});
|
||||
test("install with version 1.1.1 available as folder", async () => {
|
||||
mockPathExists.mockImplementation((path) => path === "C:\\Modules\\az_1.1.1");
|
||||
const installer = new AzModuleInstaller("1.1.1");
|
||||
const spyTryInstallingLatest = jest.spyOn(<any>installer, "tryInstallingLatest");
|
||||
const spyTryInstallFromFolder = jest.spyOn(<any>installer, "tryInstallFromFolder");
|
||||
const mockTryInstalledTrue = jest.fn(async () => expect(installer["installResult"]["isInstalled"]).toBeTruthy());
|
||||
installer["tryInstallFromZip"] = mockTryInstalledTrue;
|
||||
installer["tryInstallFromGHRelease"] = mockTryInstalledTrue;
|
||||
installer["tryInstallFromPSGallery"] = mockTryInstalledTrue;
|
||||
const result = await installer.install();
|
||||
expect(result).toEqual({ isInstalled: true, moduleSource: "hostedAgentFolder" });
|
||||
expect(spyTryInstallingLatest).toBeCalledTimes(1);
|
||||
expect(spyTryInstallFromFolder).toBeCalledTimes(1);
|
||||
expect(mockTryInstalledTrue).toBeCalledTimes(3);
|
||||
});
|
||||
test("install with version 1.1.1 available as zip", async () => {
|
||||
mockPathExists.mockImplementation((path) => path === "C:\\Modules\\az_1.1.1.zip");
|
||||
const installer = new AzModuleInstaller("1.1.1");
|
||||
const spyTryInstallingLatest = jest.spyOn(<any>installer, "tryInstallingLatest");
|
||||
const spyTryInstallFromFolder = jest.spyOn(<any>installer, "tryInstallFromFolder");
|
||||
const spyTryInstallFromZip = jest.spyOn(<any>installer, "tryInstallFromZip");
|
||||
const mockTryInstalledTrue = jest.fn(async () => expect(installer["installResult"]["isInstalled"]).toBeTruthy());
|
||||
installer["tryInstallFromGHRelease"] = mockTryInstalledTrue;
|
||||
installer["tryInstallFromPSGallery"] = mockTryInstalledTrue;
|
||||
const result = await installer.install();
|
||||
expect(result).toEqual({ isInstalled: true, moduleSource: "hostedAgentZip" });
|
||||
expect(spyTryInstallingLatest).toBeCalledTimes(1);
|
||||
expect(spyTryInstallFromFolder).toBeCalledTimes(1);
|
||||
expect(spyTryInstallFromZip).toBeCalledTimes(1);
|
||||
expect(mockTryInstalledTrue).toBeCalledTimes(2);
|
||||
});
|
||||
test("install with version 1.1.1 from GHRelease", async () => {
|
||||
const installer = new AzModuleInstaller("1.1.1");
|
||||
installer["getDownloadUrlFromGHRelease"] = jest.fn().mockReturnValue("downloadUrl");
|
||||
|
|
|
@ -42,22 +42,17 @@ describe('Testing setPSModulePath', () => {
|
|||
process.env.RUNNER_OS = savedRunnerOS;
|
||||
});
|
||||
|
||||
test('PSModulePath with azPSVersion non-empty', () => {
|
||||
test('PSModulePath with azPSVersion non-empty', async () => {
|
||||
process.env.RUNNER_OS = "Windows";
|
||||
Utils.setPSModulePath(version);
|
||||
await Utils.setPSModulePath(version);
|
||||
expect(process.env.PSModulePath).toContain(version);
|
||||
});
|
||||
test('PSModulePath with azPSVersion empty', () => {
|
||||
test('PSModulePath with azPSVersion empty', async () => {
|
||||
process.env.RUNNER_OS = "Linux";
|
||||
const prevPSModulePath = process.env.PSModulePath;
|
||||
Utils.setPSModulePath();
|
||||
await Utils.setPSModulePath();
|
||||
expect(process.env.PSModulePath).not.toEqual(prevPSModulePath);
|
||||
});
|
||||
test('setPSModulePath should throw for MacOS', () => {
|
||||
process.env.RUNNER_OS = "Darwin";
|
||||
expect(() => Utils.setPSModulePath()).toThrow();
|
||||
expect(() => Utils.setPSModulePath(version)).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Testing getLatestModule', () => {
|
||||
|
@ -93,7 +88,6 @@ describe('Testing isHostedAgent', () => {
|
|||
test('Should return true when file layout check script returns true', async () => {
|
||||
mockExecutePowerShellCommandOutput = "True";
|
||||
const isHostedAgentResult = await Utils.isHostedAgent("/usr/share");
|
||||
expect(mockPowerShellToolRunnerInit).toHaveBeenCalledTimes(1);
|
||||
expect(mockExecutePowerShellCommand).toHaveBeenCalledTimes(1);
|
||||
expect(mockExecutePowerShellCommand.mock.calls[0][0]).toBe('Test-Path (Join-Path "/usr/share" "az_*")');
|
||||
expect(isHostedAgentResult).toBeTruthy();
|
||||
|
@ -136,7 +130,6 @@ describe('Testing saveAzModule', () => {
|
|||
test('Should run without throwing when script succeeds with exit code 0', async () => {
|
||||
mockExecutePowerShellScriptBlockExitCode = 0;
|
||||
await Utils.saveAzModule("1.1.1", "/usr/share/az_1.1.1");
|
||||
expect(mockPowerShellToolRunnerInit).toHaveBeenCalledTimes(1);
|
||||
expect(mockExecutePowerShellScriptBlock).toHaveBeenCalledTimes(1);
|
||||
expect(mockExecutePowerShellScriptBlock.mock.calls[0][0]).toContain(
|
||||
"Save-Module -Path /usr/share/az_1.1.1 -Name Az -RequiredVersion 1.1.1 -Force -ErrorAction Stop");
|
||||
|
|
|
@ -4,6 +4,8 @@ import * as os from 'os';
|
|||
import { ArchiveTools } from './Utilities/ArchiveTools';
|
||||
import FileUtils from './Utilities/FileUtils';
|
||||
import Utils from './Utilities/Utils';
|
||||
import path from 'path';
|
||||
import Constants from './Constants';
|
||||
|
||||
export interface InstallResult {
|
||||
moduleSource: string;
|
||||
|
@ -36,20 +38,11 @@ export class AzModuleInstaller {
|
|||
};
|
||||
const platform = (process.env.RUNNER_OS || os.type())?.toLowerCase();
|
||||
core.debug(`Platform: ${platform}`);
|
||||
switch(platform) {
|
||||
case "windows":
|
||||
case "windows_nt":
|
||||
this.isWin = true;
|
||||
this.moduleRoot = "C:\\Modules";
|
||||
this.modulePath = `${this.moduleRoot}\\az_${this.version}`
|
||||
break;
|
||||
case "linux":
|
||||
this.moduleRoot = "/usr/share";
|
||||
this.modulePath = `${this.moduleRoot}/az_${this.version}`
|
||||
break;
|
||||
default:
|
||||
throw `OS ${platform} not supported`;
|
||||
this.moduleRoot = Utils.getDefaultAzInstallFolder(platform);
|
||||
if(platform == "windows" || platform == "windows_nt"){
|
||||
this.isWin = true;
|
||||
}
|
||||
this.modulePath = path.join(this.moduleRoot, `${Constants.prefix}${this.version}`);
|
||||
this.moduleZipPath = `${this.modulePath}.zip`;
|
||||
}
|
||||
|
||||
|
@ -137,7 +130,7 @@ export class AzModuleInstaller {
|
|||
};
|
||||
} catch (err) {
|
||||
core.debug(err);
|
||||
console.log("Download from GHRelease failed, will fallback to PSGallery");
|
||||
core.info("Download from GHRelease failed, will fallback to PSGallery");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,13 +5,13 @@ import Constants from "./Constants";
|
|||
|
||||
export default class InitializeAzure {
|
||||
static async importAzModule(azPSVersion: string) {
|
||||
Utils.setPSModulePath();
|
||||
await Utils.setPSModulePath();
|
||||
if (azPSVersion === "latest") {
|
||||
azPSVersion = await Utils.getLatestModule(Constants.moduleName);
|
||||
} else {
|
||||
await Utils.checkModuleVersion(Constants.moduleName, azPSVersion);
|
||||
}
|
||||
core.debug(`Az Module version used: ${azPSVersion}`);
|
||||
Utils.setPSModulePath(`${Constants.prefix}${azPSVersion}`);
|
||||
await Utils.setPSModulePath(`${Constants.prefix}${azPSVersion}`);
|
||||
}
|
||||
}
|
|
@ -38,7 +38,6 @@ export default class ScriptRunner {
|
|||
this.inlineScript, this.errorActionPreference);
|
||||
ScriptRunner.filePath = await FileUtils.createScriptFile(scriptToExecute);
|
||||
core.debug(`script file to run: ${ScriptRunner.filePath}`);
|
||||
await PowerShellToolRunner.init();
|
||||
const exitCode: number = await PowerShellToolRunner.executePowerShellScriptBlock(ScriptRunner.filePath, options);
|
||||
if (exitCode !== 0) {
|
||||
core.setOutput(`Azure PowerShell exited with code:`, exitCode.toString());
|
||||
|
|
|
@ -34,7 +34,6 @@ export class ArchiveTools {
|
|||
$ProgressPreference = 'SilentlyContinue'
|
||||
Expand-Archive -Path ${zipPath} -DestinationPath ${destination}
|
||||
$ProgressPreference = $prevProgressPref`;
|
||||
await PowerShellToolRunner.init();
|
||||
const exitCode = await PowerShellToolRunner.executePowerShellScriptBlock(script);
|
||||
if (exitCode != 0) {
|
||||
throw new Error(`Extraction using Expand-Archive cmdlet failed from ${zipPath} to ${destination}`);
|
||||
|
|
|
@ -11,10 +11,12 @@ export default class PowerShellToolRunner {
|
|||
}
|
||||
|
||||
static async executePowerShellCommand(command: string, options: any = {}) {
|
||||
await PowerShellToolRunner.init();
|
||||
await exec.exec(`"${PowerShellToolRunner.psPath}" -NoLogo -NoProfile -NonInteractive -Command ${command}`, [], options);
|
||||
}
|
||||
|
||||
static async executePowerShellScriptBlock(scriptBlock: string, options: any = {}): Promise<number> {
|
||||
await PowerShellToolRunner.init();
|
||||
const exitCode: number = await exec.exec(`"${PowerShellToolRunner.psPath}" -NoLogo -NoProfile -NonInteractive -Command`,
|
||||
[scriptBlock], options);
|
||||
return exitCode;
|
||||
|
|
|
@ -3,6 +3,8 @@ import * as os from 'os';
|
|||
import Constants from '../Constants';
|
||||
import PowerShellToolRunner from '../Utilities/PowerShellToolRunner';
|
||||
import ScriptBuilder from './ScriptBuilder';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
|
||||
export default class Utils {
|
||||
/**
|
||||
|
@ -11,24 +13,66 @@ export default class Utils {
|
|||
* If azPSVersion is empty, folder path in which all Az modules are present are set
|
||||
* If azPSVersion is not empty, folder path of exact Az module version is set
|
||||
*/
|
||||
static setPSModulePath(azPSVersion: string = "") {
|
||||
let modulePath: string = "";
|
||||
static async setPSModulePath(azPSVersion: string = "") {
|
||||
let output: string = "";
|
||||
const options: any = {
|
||||
listeners: {
|
||||
stdout: (data: Buffer) => {
|
||||
output += data.toString();
|
||||
}
|
||||
}
|
||||
};
|
||||
await PowerShellToolRunner.executePowerShellScriptBlock("$env:PSModulePath", options);
|
||||
const defaultPSModulePath = output.trim();
|
||||
|
||||
const runner: string = process.env.RUNNER_OS || os.type();
|
||||
switch (runner.toLowerCase()) {
|
||||
let defaultAzInstallFolder:string = Utils.getDefaultAzInstallFolder(runner.toLowerCase());
|
||||
let modulePath: string = path.join(defaultAzInstallFolder, `${azPSVersion}`);
|
||||
process.env.PSModulePath = `${modulePath}${path.delimiter}${defaultPSModulePath}`;
|
||||
}
|
||||
|
||||
static getDefaultAzInstallFolder(os:string): string{
|
||||
let defaultAzInstallFolder = "";
|
||||
switch (os) {
|
||||
case "linux":
|
||||
modulePath = `/usr/share/${azPSVersion}:`;
|
||||
defaultAzInstallFolder = "/usr/share";
|
||||
break;
|
||||
case "windows":
|
||||
case "windows_nt":
|
||||
modulePath = `C:\\Modules\\${azPSVersion};`;
|
||||
defaultAzInstallFolder = "C:\\Modules";
|
||||
break;
|
||||
case "macos":
|
||||
case "darwin":
|
||||
throw new Error(`OS not supported`);
|
||||
default:
|
||||
throw new Error(`Unknown os: ${runner.toLowerCase()}`);
|
||||
defaultAzInstallFolder = "";
|
||||
break;
|
||||
}
|
||||
process.env.PSModulePath = `${modulePath}${process.env.PSModulePath}`;
|
||||
|
||||
if(Utils.isFolderExistAndWritable(defaultAzInstallFolder)){
|
||||
return defaultAzInstallFolder;
|
||||
}
|
||||
if(Utils.isFolderExistAndWritable(process.env.RUNNER_TOOL_CACHE)){
|
||||
return process.env.RUNNER_TOOL_CACHE;
|
||||
}
|
||||
return process.cwd();
|
||||
}
|
||||
|
||||
static isFolderExistAndWritable(folderPath:string) : boolean{
|
||||
if(!folderPath){
|
||||
return false;
|
||||
}
|
||||
if (!fs.existsSync(folderPath)) {
|
||||
return false;
|
||||
}
|
||||
if (!fs.lstatSync(folderPath).isDirectory() ) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
fs.accessSync(folderPath, fs.constants.W_OK)
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static async getLatestModule(moduleName: string): Promise<string> {
|
||||
|
@ -40,7 +84,6 @@ export default class Utils {
|
|||
}
|
||||
}
|
||||
};
|
||||
await PowerShellToolRunner.init();
|
||||
await PowerShellToolRunner.executePowerShellScriptBlock(new ScriptBuilder()
|
||||
.getLatestModuleScript(moduleName), options);
|
||||
const outputJson = JSON.parse(output.trim());
|
||||
|
@ -66,7 +109,6 @@ export default class Utils {
|
|||
if (!Utils.isValidVersion(output.trim())) {
|
||||
return "";
|
||||
}
|
||||
await PowerShellToolRunner.init();
|
||||
await PowerShellToolRunner.executePowerShellCommand(new ScriptBuilder()
|
||||
.checkModuleVersionScript(moduleName, version), options);
|
||||
const outputJson = JSON.parse(output.trim());
|
||||
|
@ -93,7 +135,6 @@ export default class Utils {
|
|||
}
|
||||
}
|
||||
};
|
||||
await PowerShellToolRunner.init();
|
||||
await PowerShellToolRunner.executePowerShellCommand(script, options);
|
||||
return output.trim().toLowerCase() === "true";
|
||||
}
|
||||
|
@ -111,7 +152,6 @@ export default class Utils {
|
|||
$ProgressPreference = 'SilentlyContinue'
|
||||
Save-Module -Path ${modulePath} -Name Az -RequiredVersion ${version} -Force -ErrorAction Stop
|
||||
$ProgressPreference = $prevProgressPref`;
|
||||
await PowerShellToolRunner.init();
|
||||
const exitCode = await PowerShellToolRunner.executePowerShellScriptBlock(script);
|
||||
if (exitCode != 0) {
|
||||
throw new Error(`Download from PSGallery failed for Az ${version} to ${modulePath}`);
|
||||
|
|
Загрузка…
Ссылка в новой задаче