-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into users/shmittal/CreatingBlob
- Loading branch information
Showing
17 changed files
with
1,515 additions
and
9 deletions.
There are no files selected for viewing
41 changes: 41 additions & 0 deletions
41
Tasks/DownloadGitHubNpmPackageV1/Strings/resources.resjson/en-US/resources.resjson
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
{ | ||
"loc.friendlyName": "Download Github Npm Package", | ||
"loc.helpMarkDown": "[Learn more about this task](https://go.microsoft.com/fwlink/?LinkID=613746) or [see the npm documentation](https://docs.npmjs.com/)", | ||
"loc.description": "Install npm packages from GitHub.", | ||
"loc.instanceNameFormat": "Download GitHub Npm Package", | ||
"loc.group.displayName.customRegistries": "Custom registries and authentication", | ||
"loc.input.label.packageName": "Package Name", | ||
"loc.input.help.packageName": "Name of the package to download from github", | ||
"loc.input.label.version": "Package Version", | ||
"loc.input.help.version": "Version of the package to download from github", | ||
"loc.input.label.externalEndpoints": "Credentials for registry from GitHub", | ||
"loc.input.help.externalEndpoints": "Credentials to use for external registry from GitHub", | ||
"loc.input.label.packagesDirectory": "Destination directory", | ||
"loc.input.help.packagesDirectory": "Specifies the folder in which packages are installed. If no folder is specified, packages are restored into the default system working directory.", | ||
"loc.messages.FoundBuildCredentials": "Found build credentials", | ||
"loc.messages.NoBuildCredentials": "Could not find build credentials", | ||
"loc.messages.UnknownCommand": "Unknown command: %s", | ||
"loc.messages.MultipleProjectConfigs": "More than one project .npmrc found in $s", | ||
"loc.messages.ServiceEndpointNotDefined": "Couldn't find the service connection. Make sure the selected service connection still exists.", | ||
"loc.messages.ServiceEndpointUrlNotDefined": "Couldn't find the URL for the service connection. Make sure the service connection is correctly configured.", | ||
"loc.messages.SavingFile": "Saving file %s", | ||
"loc.messages.RestoringFile": "Restoring file %s", | ||
"loc.messages.PublishFeed": "Publishing to internal feed", | ||
"loc.messages.PublishExternal": "Publishing to external registry", | ||
"loc.messages.PackageFailedToInstall": "Package failed to install", | ||
"loc.messages.UseFeed": "Using internal feed", | ||
"loc.messages.UseNpmrc": "Using registries in .npmrc", | ||
"loc.messages.PublishRegistry": "Publishing to registry: %s", | ||
"loc.messages.UsingRegistry": "Using registry: %s", | ||
"loc.messages.AddingAuthRegistry": "Adding auth for registry: %s", | ||
"loc.messages.FoundLocalRegistries": "Found %d registries in this organization/collection", | ||
"loc.messages.ForcePackagingUrl": "Packaging collection URL forced to: %s", | ||
"loc.messages.DebugLogNotFound": "Couldn't find a debug log in the cache or working directory", | ||
"loc.messages.NpmFailed": "Npm failed with return code: %s", | ||
"loc.messages.FoundNpmDebugLog": "Found npm debug log, make sure the path matches with the one in npm's output: %s", | ||
"loc.messages.TestDebugLog": "Trying debug log location: %s", | ||
"loc.messages.OverridingProjectNpmrc": "Overriding project .npmrc: %s", | ||
"loc.messages.RestoringProjectNpmrc": "Restoring project .npmrc", | ||
"loc.messages.WorkingDirectoryNotDirectory": "Please change your working directory to a valid directory", | ||
"loc.messages.NGCommon_AreaNotFoundInSps": "Unable to locate the '%s' [%s] area. The service containing that area may not be available in your region." | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"common": [ | ||
{ | ||
"module": "../Common/utility-common", | ||
"type": "node", | ||
"compile": true | ||
}, | ||
{ | ||
"module": "../Common/packaging-common", | ||
"type": "node", | ||
"compile": true | ||
} | ||
], | ||
"rm": [ | ||
{ | ||
"items": [ | ||
"node_modules/packaging-common/node_modules/azure-pipelines-task-lib" | ||
], | ||
"options": "-Rf" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import * as path from 'path'; | ||
|
||
import {IExecSyncResult} from 'azure-pipelines-task-lib/toolrunner'; | ||
import * as tl from 'azure-pipelines-task-lib/task'; | ||
|
||
import * as npminstall from './npminstall'; | ||
import * as util from 'packaging-common/util'; | ||
|
||
async function main(): Promise<void> { | ||
tl.setResourcePath(path.join(__dirname, 'task.json')); | ||
await _logNpmStartupVariables(); | ||
npminstall.run(); | ||
} | ||
|
||
async function _logNpmStartupVariables() { | ||
try { | ||
// Log the NPM version | ||
let version: string; | ||
try { | ||
const syncResult: IExecSyncResult = tl.execSync('npm', '--version'); | ||
if (syncResult.stdout) { | ||
version = syncResult.stdout.trim(); | ||
} | ||
} catch (err) { | ||
tl.debug(`Unable to get NPM config info. Err:( ${err} )`); | ||
} | ||
} catch (err) { | ||
tl.debug(`Unable to log NPM task telemetry. Err:( ${err} )`); | ||
} | ||
} | ||
|
||
main().catch(error => { | ||
tl.rmRF(util.getTempPath()); | ||
tl.setResult(tl.TaskResult.Failed, error); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
import * as tl from 'azure-pipelines-task-lib/task'; | ||
|
||
import { NpmToolRunner } from './npmtoolrunner'; | ||
import * as util from 'packaging-common/util'; | ||
import * as npmutil from 'packaging-common/npm/npmutil'; | ||
import * as path from 'path'; | ||
import * as request from 'request'; | ||
|
||
export async function run(): Promise<void> { | ||
try { | ||
const npmrc = npmutil.getTempNpmrcPath(); | ||
let owner: string = ""; | ||
let token: string = ""; | ||
|
||
const endpointName = tl.getInput("externalEndpoints"); | ||
if (!endpointName) { | ||
tl.error("Couldn't find the specified service connection."); | ||
tl.setResult(tl.TaskResult.Failed, tl.loc('PackageFailedToInstall')); | ||
} | ||
|
||
let packageNameInput: string = tl.getInput("packageName"); | ||
let packageVersion: string = tl.getInput("version") || ""; | ||
|
||
if (!packageNameInput || packageNameInput.indexOf("/") < 0) | ||
{ | ||
throw Error(tl.loc('Error_InvalidPackageName')); | ||
} | ||
else { | ||
packageNameInput = packageNameInput.split("/")[1]; | ||
} | ||
|
||
owner = await GetGitHubUser(endpointName); // we will always have a single connection | ||
token = getEndpointAuthData(endpointName); | ||
|
||
const url = "https://npm.pkg.github.com/" + owner; | ||
let authDetails = "//npm.pkg.github.com/:_authToken=" + token; | ||
tl.debug(tl.loc('UsingRegistry', url)); | ||
tl.mkdirP | ||
|
||
npmutil.appendToNpmrc(npmrc, `registry=${url}\n`); | ||
npmutil.appendToNpmrc(npmrc, `${authDetails}\n`); | ||
|
||
const packageDownloadPath = getProjectPath(packageNameInput); | ||
|
||
const npm = new NpmToolRunner(path.dirname(npmrc), npmrc, false); | ||
let packageName = owner.toLowerCase() + "/" + packageNameInput.toLowerCase(); | ||
let command: string = ""; | ||
if (packageVersion == "" || packageVersion == undefined) { | ||
command = "install --prefix " + packageDownloadPath + " @" + packageName; | ||
} else { | ||
command = "install --prefix " + packageDownloadPath + " @" + packageName + "@" + packageVersion; | ||
} | ||
|
||
npm.line(command); | ||
npm.execSync(); | ||
|
||
tl.rmRF(npmrc); | ||
} catch (err) { | ||
tl.setResult(tl.TaskResult.Failed, "Some error occurred:" + err); | ||
} | ||
} | ||
|
||
export function getProjectPath(packageName: string): string { | ||
const tempNpmrcDir | ||
= tl.getVariable('Agent.BuildDirectory') | ||
|| tl.getVariable('Agent.TempDirectory'); | ||
const tempPath = path.join(tempNpmrcDir, packageName); | ||
if (tl.exist(tempPath) === false) { | ||
tl.mkdirP(tempPath); | ||
} | ||
|
||
return tempPath; | ||
} | ||
|
||
function createProjectFile(projectDirectory: string, owner: string): string { | ||
let version: string = tl.getInput("version"); | ||
let packageNameInput : string = tl.getInput("packageName"); | ||
let packageName = owner.toLowerCase() + "/" + packageNameInput.split('/')[1].toLowerCase(); | ||
let projectFile: string = ` | ||
{ | ||
"name": "testProject", | ||
"version": "${version}", | ||
"main": "index.js", | ||
"author": "", | ||
"license": "MIT", | ||
"dependencies": { | ||
"@${packageName}": "${version}" | ||
} | ||
}` | ||
|
||
tl.writeFile(path.join(projectDirectory, "package.json"), projectFile); | ||
console.log("npmrc = " + path.join(projectDirectory, "package.json")); | ||
return path.join(projectDirectory, "package.json"); | ||
} | ||
|
||
function GetGitHubUser(endpointId: string): Promise<string> { | ||
let externalAuth = tl.getEndpointAuthorization(endpointId, true); | ||
let scheme = tl.getEndpointAuthorizationScheme(endpointId, true).toLowerCase(); | ||
|
||
if (!(scheme == "token" || scheme == "personalaccesstoken")) { | ||
return new Promise((resolve, reject) => { | ||
resolve(""); | ||
}); | ||
} | ||
|
||
let token = ""; | ||
if (scheme == "token") { | ||
token = externalAuth.parameters["AccessToken"]; | ||
} else if (scheme == "personalaccesstoken") { | ||
token = externalAuth.parameters["accessToken"]; | ||
} | ||
|
||
var url = "https://api.github.com/user"; | ||
|
||
return new Promise((resolve, reject) => { | ||
request.get({ | ||
url : url, | ||
headers : { | ||
"Authorization": "Token " + token, | ||
"User-Agent": "azure-pipelines" | ||
} | ||
}, function(error, response, body) { | ||
if (error) reject(error); | ||
let responseJson = JSON.parse(body); | ||
resolve(responseJson["login"]); | ||
}); | ||
}); | ||
} | ||
|
||
function getEndpointAuthData(endpointName: string): string { | ||
let externalAuth = tl.getEndpointAuthorization(endpointName, true); | ||
let scheme = tl.getEndpointAuthorizationScheme(endpointName, true).toLowerCase(); | ||
let token = ""; | ||
switch(scheme) { | ||
case "token": | ||
token = externalAuth.parameters["AccessToken"]; | ||
break; | ||
case "personalaccesstoken": | ||
token = externalAuth.parameters["accessToken"]; | ||
break; | ||
case "usernamepassword": | ||
case "none": | ||
break; | ||
default: | ||
break; | ||
} | ||
|
||
return token; | ||
} |
Oops, something went wrong.