Skip to content

Commit 884e3e2

Browse files
authored
Refactor func CLI installation pretest logic (#4731)
1 parent d71743d commit 884e3e2

File tree

3 files changed

+90
-1117
lines changed

3 files changed

+90
-1117
lines changed

gulpfile.ts

Lines changed: 82 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,13 @@
55

66
import * as msRest from '@azure/ms-rest-js';
77
import { gulp_webpack } from '@microsoft/vscode-azext-dev';
8+
import { exec } from 'child_process';
9+
import * as extract from 'extract-zip';
810
import * as fse from 'fs-extra';
911
import * as gulp from 'gulp';
10-
import * as chmod from 'gulp-chmod';
11-
import * as decompress from 'gulp-decompress';
12-
import * as filter from 'gulp-filter';
12+
import * as https from 'https';
1313
import * as os from 'os';
1414
import * as path from 'path';
15-
import * as request from 'request';
16-
import * as buffer from 'vinyl-buffer';
17-
import * as source from 'vinyl-source-stream';
1815

1916
async function prepareForWebpack(): Promise<void> {
2017
const mainJsPath: string = path.join(__dirname, 'main.js');
@@ -25,7 +22,7 @@ async function prepareForWebpack(): Promise<void> {
2522
await fse.writeFile(mainJsPath, contents);
2623
}
2724

28-
let downloadLink;
25+
let downloadLink: string;
2926
async function getFuncLink() {
3027
const client = new msRest.ServiceClient();
3128
const cliFeed = JSON.parse((await client.sendRequest({ method: 'GET', url: 'https://aka.ms/V00v5v' })).bodyAsText as string);
@@ -53,32 +50,93 @@ function matchesCliFeedOS(platform: string) {
5350
}
5451
}
5552

56-
function installFuncCli() {
57-
const funcDir = path.join(os.homedir(), 'tools', 'func');
53+
async function cleanReadme() {
54+
const readmePath: string = path.join(__dirname, 'README.md');
55+
let data: string = (await fse.readFile(readmePath)).toString();
56+
data = data.replace(/<!-- region exclude-from-marketplace -->.*?<!-- endregion exclude-from-marketplace -->/gis, '');
57+
await fse.writeFile(readmePath, data);
58+
}
59+
60+
const funcDir = path.join(os.homedir(), 'tools', 'func');
61+
const funcZip = 'funccli.zip';
62+
const funcExecutable = process.platform === 'win32' ? 'func.exe' : 'func';
63+
64+
async function downloadFuncCli() {
5865
if (fse.pathExistsSync(funcDir)) {
5966
console.log('Removing old install of func.');
6067
fse.removeSync(funcDir);
6168
}
6269

63-
const funcFilter = filter('func', { restore: true });
64-
return request(downloadLink)
65-
.pipe(source('funccli.zip'))
66-
.pipe(buffer())
67-
.pipe(decompress())
68-
.pipe(funcFilter)
69-
.pipe(chmod({ execute: true }))
70-
.pipe(funcFilter.restore)
71-
.pipe(gulp.dest(funcDir));
70+
const funcZipPath = path.join(funcDir, funcZip);
71+
await fse.ensureFile(funcZipPath);
72+
73+
try {
74+
await download(downloadLink, funcZipPath);
75+
console.log('Successfully downloaded the func CLI zip at ' + funcZipPath);
76+
} catch (e) {
77+
console.log('Failed to download the func CLI zip at ' + funcZipPath);
78+
console.error(e);
79+
throw e;
80+
}
7281
}
7382

74-
async function cleanReadme() {
75-
const readmePath: string = path.join(__dirname, 'README.md');
76-
let data: string = (await fse.readFile(readmePath)).toString();
77-
data = data.replace(/<!-- region exclude-from-marketplace -->.*?<!-- endregion exclude-from-marketplace -->/gis, '');
78-
await fse.writeFile(readmePath, data);
83+
function download(url: string, targetPath: string): Promise<void> {
84+
return new Promise((resolve, reject) => {
85+
const request = https.get(url, (response) => {
86+
if (response.statusCode !== 200) {
87+
reject(new Error('Request for func CLI responded with status code: ' + response.statusCode));
88+
return;
89+
}
90+
response.on('error', (error) => reject(new Error('Response error: ' + error.message)));
91+
92+
const pipeline = response.pipe(fse.createWriteStream(targetPath));
93+
pipeline.on('error', (error) => reject(new Error('Write error: ' + error.message)));
94+
pipeline.on('finish', resolve);
95+
});
96+
97+
request.on('error', (error) => reject(new Error('Failed to make GET request: ' + error.message)));
98+
});
99+
}
100+
101+
async function extractFuncCli() {
102+
const funcZipPath: string = path.join(funcDir, funcZip);
103+
104+
try {
105+
// Extract
106+
await extract(funcZipPath, { dir: funcDir });
107+
console.log('Successfully extracted func CLI.');
108+
109+
// chmod +x
110+
console.log('Setting executable permissions...');
111+
await fse.chmod(path.join(funcDir, funcExecutable), 755);
112+
console.log('Successfully set executable permissions.');
113+
} catch (e) {
114+
console.log('Failed to install func CLI.')
115+
console.error(e);
116+
throw e;
117+
} finally {
118+
await fse.remove(funcZipPath);
119+
}
120+
}
121+
122+
async function printFuncVersion() {
123+
const funcExecutablePath = path.join(funcDir, funcExecutable);
124+
125+
await new Promise<void>((resolve, reject) => {
126+
exec(`"${funcExecutablePath}" --version`, (error, stdout, stderr) => {
127+
if (stderr || error) {
128+
const failed = new Error(`Failed to verify: ${stderr || error}`);
129+
console.error(failed);
130+
reject(failed);
131+
} else {
132+
console.log(`Verified func CLI version:\n${stdout}`);
133+
resolve();
134+
}
135+
});
136+
});
79137
}
80138

81139
exports['webpack-dev'] = gulp.series(prepareForWebpack, () => gulp_webpack('development'));
82140
exports['webpack-prod'] = gulp.series(prepareForWebpack, () => gulp_webpack('production'));
83-
exports.preTest = gulp.series(getFuncLink, installFuncCli);
141+
exports.preTest = gulp.series(getFuncLink, downloadFuncCli, extractFuncCli, printFuncVersion);
84142
exports.cleanReadme = cleanReadme;

0 commit comments

Comments
 (0)