Skip to content

Commit

Permalink
apply install script in azdo setup-azd and release azdo extension 1.0…
Browse files Browse the repository at this point in the history
….0 (#4703)

* apply install script in azdo

* align with gha

* update extension and test it in real case

* update test case for installation script

* increase time out

* revert

* apply suggestions

* format with typescript formatter

* fix test on timeout

* revert it back

* test with this.timeout

* apply the same for success
  • Loading branch information
hemarina authored Jan 29, 2025
1 parent 9004588 commit 7665df1
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 112 deletions.
8 changes: 8 additions & 0 deletions ext/azuredevops/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ behalf.

From `setupAzd` folder, run `npm test`

### Testing in Azure Devops using private extension

- Update `publisher` to your test use case and change `galleryFlags` to `private` in `vss-extension.json`.
- Use a new `id` in `setupAzd/task.json`.
- Run the `build` steps to produce the `vsix` release artifact.
- Publish it to the Marketplace in private mode and share it with your test organization.
- Go to your test organization and install the shared extension. Then, you could run the private extension for testing.

## Release

- Update `setupAzd/task.json` with the `version` number.
Expand Down
118 changes: 26 additions & 92 deletions ext/azuredevops/setupAzd/index.ts
Original file line number Diff line number Diff line change
@@ -1,109 +1,43 @@
import * as task from 'azure-pipelines-task-lib/task';
import * as task from 'azure-pipelines-task-lib/task'
import * as cp from 'child_process'
import path from 'path';
import * as fs from 'fs'
import download from 'download';
import decompress from 'decompress';

export async function runMain(): Promise<void> {
try {
task.setTaskVariable('hasRunMain', 'true');
const version = task.getInput('version') || 'latest'

console.log("using version: " + version)

// get architecture and os
const architecture = process.arch
task.setTaskVariable('hasRunMain', 'true')
const os = process.platform

// map for different platform and arch
const extensionMap = {
linux: '.tar.gz',
darwin: '.zip',
win32: '.zip'
const localAppData = process.env.LocalAppData
const envPath = process.env.PATH
if (os === 'win32' && !localAppData) {
task.setResult(task.TaskResult.Failed, 'LocalAppData environment variable is not defined.')
return
}

const exeMap = {
linux: '',
darwin: '',
win32: '.exe'
if (!envPath) {
task.setResult(task.TaskResult.Failed, 'PATH environment variable is not defined.')
return
}
const version = task.getInput('version') || 'latest'
const windowsInstallScript = `powershell -c "$scriptPath = \\"$($env:TEMP)\\install-azd.ps1\\"; Invoke-RestMethod 'https://aka.ms/install-azd.ps1' -OutFile $scriptPath; . $scriptPath -Version '${version}' -Verbose:$true; Remove-Item $scriptPath"`
const linuxOrMacOSInstallScript = `curl -fsSL https://aka.ms/install-azd.sh | sudo bash -s -- --version ${version} --verbose`

const arm64Map = {
x64: 'amd64',
arm64: 'arm64-beta'
}

const platformMap = {
linux: 'linux',
darwin: 'darwin',
win32: 'windows'
}

// get install url
const installArray = installUrlForOS(
os,
architecture,
platformMap,
arm64Map,
extensionMap,
exeMap
)

const url = `https://azd-release-gfgac2cmf7b8cuay.b02.azurefd.net/azd/standalone/release/${version}/${installArray[0]}`

console.log(`The Azure Developer CLI collects usage data and sends that usage data to Microsoft in order to help us improve your experience.
You can opt-out of telemetry by setting the AZURE_DEV_COLLECT_TELEMETRY environment variable to 'no' in the shell you use.
Read more about Azure Developer CLI telemetry: https://github.com/Azure/azure-dev#data-collection`)
console.log(`Installing azd version ${version} on ${os}.`)

console.log(`Installing azd from ${url}`)
const buffer = await download(url);
const extractedTo = path.join(task.cwd(), 'azd-install');
await decompress(buffer, extractedTo);
if (os === 'win32') {
console.log(cp.execSync(windowsInstallScript).toString())

let binName
if (os !== 'win32') {
binName = 'azd';
// Add azd to PATH
task.setVariable('PATH', `${envPath};${localAppData}\\Programs\\Azure Dev CLI`)
} else {
binName = 'azd.exe';
console.log(cp.execSync(linuxOrMacOSInstallScript).toString())
}
const binPath = path.join(extractedTo, binName);

fs.symlinkSync(
path.join(extractedTo, installArray[1]),
binPath
)
task.prependPath(extractedTo)
console.log(`azd installed to ${extractedTo}`)

task.exec(binPath, 'version')
// Run `azd version` to make sure if azd installation failed, it returns error on windows
if (os === 'win32') {
const azdVersion = `"${localAppData}\\Programs\\Azure Dev CLI\\azd.exe" version`
cp.execSync(azdVersion)
}
} catch (err: any) {
task.setResult(task.TaskResult.Failed, err.message);
}
}

function installUrlForOS(
os: string,
architecture: string,
platformMap: Record<string, string>,
archMap: Record<string, string>,
extensionMap: Record<string, string>,
exeMap: Record<string, string>
): [string, string] {
const platformPart = `${platformMap[os]}`
const archPart = `${archMap[architecture]}`

if (platformPart === `undefined` || archPart === `undefined`) {
throw new Error(
`Unsupported platform and architecture: ${architecture} ${os}`
)
task.setResult(task.TaskResult.Failed, err.message)
}

const installUrl = `azd-${platformPart}-${archPart}${extensionMap[os]}`
const installUrlForRename = `azd-${platformPart}-${archPart}${exeMap[os]}`

return [installUrl, installUrlForRename]
}

runMain();
runMain()
4 changes: 2 additions & 2 deletions ext/azuredevops/setupAzd/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
"category": "Utility",
"author": "AzureDeveloperCLI",
"version": {
"Major": 0,
"Minor": 15,
"Major": 1,
"Minor": 0,
"Patch": 0
},
"instanceNameFormat": "Installs azd: $(rootFolder)",
Expand Down
15 changes: 7 additions & 8 deletions ext/azuredevops/setupAzd/tests/InstallFail.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
import * as path from 'path';
import * as assert from 'assert';
import * as ttm from 'azure-pipelines-task-lib/mock-test';
import * as fs from 'fs'
import { log } from 'console';
import * as fs from 'fs';

describe('setup azd tests - fails', function () {
setTimeout(() => { }, 60000);
before(function () { });
describe('setup azd tests - fails', function() {
this.timeout(60000);
before(function() { });
afterEach(() => {
fs.rmSync('path', { recursive: true, force: true })
});

it('should fail with invalid version', function (done: Mocha.Done) {
setTimeout(() => { }, 10000);
it('should fail with invalid version', function(done: Mocha.Done) {
this.timeout(10000);
let tp = path.join(__dirname, 'invalidVersion.js');
let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);

tr.runAsync().then(() => {
assert.equal(tr.succeeded, false, 'should have failed');
assert.equal(tr.warningIssues.length, 0, "should have no warnings");
assert.equal(tr.errorIssues.length, 1, "should have error");
assert.equal(tr.stdout.indexOf('Response code 404 (The specified blob does not exist.)') >= 0, true, "should display error");
assert.equal(tr.stdout.indexOf('Could not download from') >= 0, true, "should display error");
done();
}).catch((reason) => {
done(reason);
Expand Down
18 changes: 9 additions & 9 deletions ext/azuredevops/setupAzd/tests/InstallSuccess.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
import * as path from 'path';
import * as assert from 'assert';
import * as ttm from 'azure-pipelines-task-lib/mock-test';
import * as fs from 'fs'
import * as fs from 'fs';

describe('setup azd tests', function () {
setTimeout(() => { }, 10000);
before(function () { });
describe('setup azd tests', function() {
this.timeout(60000);
before(function() { });
afterEach(() => {
fs.rmSync('path', { recursive: true, force: true })
});

it('should succeed with empty version', function (done: Mocha.Done) {
setTimeout(() => { }, 10000);
it('should succeed with undefined version', function(done: Mocha.Done) {
this.timeout(10000);
let tp = path.join(__dirname, 'success.js');
let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
tr.runAsync().then(() => {
assert.equal(tr.succeeded, true, 'should have succeeded');
assert.equal(tr.warningIssues.length, 0, "should have no warnings");
assert.equal(tr.errorIssues.length, 0, "should have no errors");
assert.equal(tr.stdout.indexOf('using version: latest') >= 0, true, "should display version");
assert.equal(tr.stdout.indexOf('Installing azd version latest') >= 0, true, "should display version");
done();
}).catch((reason) => {
done(reason);
});
});

it('should succeed with version', function (done: Mocha.Done) {
it('should succeed with version', function(done: Mocha.Done) {
setTimeout(() => { }, 10000);
let tp = path.join(__dirname, 'successVersion.js');
let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
Expand All @@ -34,7 +34,7 @@ describe('setup azd tests', function () {
assert.equal(tr.succeeded, true, 'should have succeeded');
assert.equal(tr.warningIssues.length, 0, "should have no warnings");
assert.equal(tr.errorIssues.length, 0, "should have no errors");
assert.equal(tr.stdout.indexOf('using version: 1.0.0') >= 0, true, "should display version");
assert.equal(tr.stdout.indexOf('Installing azd version 1.0.0') >= 0, true, "should display version");
done();
}).catch((reason) => {
done(reason);
Expand Down
2 changes: 1 addition & 1 deletion ext/azuredevops/vss-extension.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"manifestVersion": 1,
"id": "azd",
"name": "Install azd",
"version": "0.15.0",
"version": "1.0.0",
"publisher": "ms-azuretools",
"targets": [
{
Expand Down

0 comments on commit 7665df1

Please sign in to comment.