Merge pull request #25 from liang2zhu1/master

Support PAT token on command line
This commit is contained in:
Liang Zhu 2018-09-27 19:26:59 -07:00 коммит произвёл GitHub
Родитель ae22dc0b37 c55d6d0bdf
Коммит bc5d36013d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
12 изменённых файлов: 90 добавлений и 66 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -1,3 +1,4 @@
node_modules/*
output/*
build/*
test/*

44
package-lock.json сгенерированный
Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "process-import-export",
"version": "0.9.3",
"name": "process-migrator",
"version": "0.9.4",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -63,6 +63,27 @@
"resolved": "https://registry.npmjs.org/@types/requirejs/-/requirejs-2.1.31.tgz",
"integrity": "sha512-b2soeyuU76rMbcRJ4e0hEl0tbMhFwZeTC0VZnfuWlfGlk6BwWNsev6kFu/twKABPX29wkX84wU2o+cEJoXsiTw=="
},
"azure-devops-node-api": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-6.6.0.tgz",
"integrity": "sha512-fF3AI0dyVyJvd3ucSDIGtexlbK7uA2dH/uh1X5Ue9bsSQQcX1cYqXWS6I7IS5/TxSzs3A3d6IXRx8zstgNGXMA==",
"requires": {
"tunnel": "0.0.4",
"typed-rest-client": "1.0.9",
"underscore": "1.8.3"
},
"dependencies": {
"typed-rest-client": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.0.9.tgz",
"integrity": "sha512-iOdwgmnP/tF6Qs+oY4iEtCf/3fnCDl7Gy9LGPJ4E3M4Wj3uaSko15FVwbsaBmnBqTJORnXBWVY5306D4HH8oiA==",
"requires": {
"tunnel": "0.0.4",
"underscore": "1.8.3"
}
}
}
},
"guid-typescript": {
"version": "1.0.7",
"resolved": "https://witiq.pkgs.visualstudio.com/_packaging/processimportexport/npm/registry/guid-typescript/-/guid-typescript-1.0.7.tgz",
@ -108,15 +129,6 @@
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.4.tgz",
"integrity": "sha1-LTeFoVjBdMmhbcLARuxfxfF0IhM="
},
"typed-rest-client": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-0.12.0.tgz",
"integrity": "sha1-Y3b1Un9CfaEh3K/f1+QeEyHgcgw=",
"requires": {
"tunnel": "0.0.4",
"underscore": "1.8.3"
}
},
"typescript": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-2.8.1.tgz",
@ -137,16 +149,6 @@
"querystring": "0.2.0"
}
},
"vso-node-api": {
"version": "6.5.0",
"resolved": "https://witiq.pkgs.visualstudio.com/_packaging/processimportexport/npm/registry/vso-node-api/-/vso-node-api-6.5.0.tgz",
"integrity": "sha512-hFjPLMJkq02zF8U+LhZ4airH0ivaiKzGdlNAQlYFB3lWuGH/UANUrl63DVPUQOyGw+7ZNQ+ufM44T6mWN92xyg==",
"requires": {
"tunnel": "0.0.4",
"typed-rest-client": "0.12.0",
"underscore": "1.8.3"
}
},
"vss-web-extension-sdk": {
"version": "5.131.0",
"resolved": "https://registry.npmjs.org/vss-web-extension-sdk/-/vss-web-extension-sdk-5.131.0.tgz",

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "process-migrator",
"version": "0.9.4",
"version": "0.9.5",
"description": "Proces import/export Node.js application",
"main": "",
"bin": {
@ -19,7 +19,8 @@
"url": "https://github.com/Microsoft/process-migrator"
},
"keywords": [
"vsts",
"azure devops",
"azure boards",
"process",
"import",
"export",
@ -41,7 +42,7 @@
"minimist": "^1.2.0",
"mkdirp": "^0.5.1",
"url": "^0.11.0",
"vso-node-api": "^6.5.0",
"azure-devops-node-api": "^6.5.0",
"vss-web-extension-sdk": "^5.131.0"
}
}

Просмотреть файл

@ -1,8 +1,8 @@
/// <reference types="vss-web-extension-sdk" />
import * as WITInterfaces from "vso-node-api/interfaces/WorkItemTrackingInterfaces";
import * as WITProcessDefinitionsInterfaces from "vso-node-api/interfaces/WorkItemTrackingProcessDefinitionsInterfaces";
import * as WITProcessInterfaces from "vso-node-api/interfaces/WorkItemTrackingProcessInterfaces";
import { WorkItemTrackingApi } from "vso-node-api/WorkItemTrackingApi";
import * as WITInterfaces from "azure-devops-node-api/interfaces/WorkItemTrackingInterfaces";
import * as WITProcessDefinitionsInterfaces from "azure-devops-node-api/interfaces/WorkItemTrackingProcessDefinitionsInterfaces";
import * as WITProcessInterfaces from "azure-devops-node-api/interfaces/WorkItemTrackingProcessInterfaces";
import { WorkItemTrackingApi } from "azure-devops-node-api/WorkItemTrackingApi";
import { getCollectionClient } from "VSS/Service";
import { WorkItemTrackingHttpClient } from "TFS/WorkItemTracking/RestClient";

Просмотреть файл

@ -5,6 +5,8 @@ export const defaultLogFileName = "output\\processMigrator.log";
export const defaultProcessFilename = "output\\process.json";
export const paramMode = "mode";
export const paramConfig = "config";
export const paramSourceToken = "sourceToken";
export const paramTargetToken = "targetToken";
export const paramOverwriteProcessOnTarget = "overwriteProcessOnTarget";
export const defaultConfiguration =
`{

Просмотреть файл

@ -1,9 +1,9 @@
import * as WITProcessDefinitionsInterfaces from "vso-node-api/interfaces/WorkItemTrackingProcessDefinitionsInterfaces";
import * as WITProcessInterfaces from "vso-node-api/interfaces/WorkItemTrackingProcessInterfaces";
import * as WITInterfaces from "vso-node-api/interfaces/WorkItemTrackingInterfaces";
import { IWorkItemTrackingProcessDefinitionsApi as WITProcessDefinitionApi } from "vso-node-api/WorkItemTrackingProcessDefinitionsApi";
import { IWorkItemTrackingProcessApi as WITProcessApi } from "vso-node-api/WorkItemTrackingProcessApi";
import { IWorkItemTrackingApi as WITApi } from "vso-node-api/WorkItemTrackingApi";
import * as WITProcessDefinitionsInterfaces from "azure-devops-node-api/interfaces/WorkItemTrackingProcessDefinitionsInterfaces";
import * as WITProcessInterfaces from "azure-devops-node-api/interfaces/WorkItemTrackingProcessInterfaces";
import * as WITInterfaces from "azure-devops-node-api/interfaces/WorkItemTrackingInterfaces";
import { IWorkItemTrackingProcessDefinitionsApi as WITProcessDefinitionApi } from "azure-devops-node-api/WorkItemTrackingProcessDefinitionsApi";
import { IWorkItemTrackingProcessApi as WITProcessApi } from "azure-devops-node-api/WorkItemTrackingProcessApi";
import { IWorkItemTrackingApi as WITApi } from "azure-devops-node-api/WorkItemTrackingApi";
export enum LogLevel {
error,
@ -26,6 +26,8 @@ export interface ICommandLineOptions {
mode: Modes;
overwriteProcessOnTarget: boolean;
config: string;
sourceToken?: string;
targetToken?: string;
}
export interface IConfigurationFile {

Просмотреть файл

@ -1,10 +1,9 @@
import * as WITProcessDefinitionsInterfaces from "vso-node-api/interfaces/WorkItemTrackingProcessDefinitionsInterfaces";
import * as WITProcessInterfaces from "vso-node-api/interfaces/WorkItemTrackingProcessInterfaces";
import * as vsts_NOREQUIRE from "vso-node-api/WebApi";
import { IWorkItemTrackingProcessDefinitionsApi as WITProcessDefinitionApi_NOREQUIRE } from "vso-node-api/WorkItemTrackingProcessDefinitionsApi";
import { IWorkItemTrackingProcessApi as WITProcessApi_NOREQUIRE } from "vso-node-api/WorkItemTrackingProcessApi";
import { IWorkItemTrackingApi as WITApi_NOREQUIRE } from "vso-node-api/WorkItemTrackingApi";
import * as WITProcessDefinitionsInterfaces from "azure-devops-node-api/interfaces/WorkItemTrackingProcessDefinitionsInterfaces";
import * as WITProcessInterfaces from "azure-devops-node-api/interfaces/WorkItemTrackingProcessInterfaces";
import * as vsts_NOREQUIRE from "azure-devops-node-api/WebApi";
import { IWorkItemTrackingProcessDefinitionsApi as WITProcessDefinitionApi_NOREQUIRE } from "azure-devops-node-api/WorkItemTrackingProcessDefinitionsApi";
import { IWorkItemTrackingProcessApi as WITProcessApi_NOREQUIRE } from "azure-devops-node-api/WorkItemTrackingProcessApi";
import { IWorkItemTrackingApi as WITApi_NOREQUIRE } from "azure-devops-node-api/WorkItemTrackingApi";
import { IConfigurationFile, IDictionaryStringTo, IProcessPayload, IWITBehaviors, IWITBehaviorsInfo, IWITFieldPicklist, IWITLayout, IWITRules, IWITStates, IWITypeFields, IRestClients } from "./Interfaces";
import { ExportError } from "./Errors";

Просмотреть файл

@ -1,12 +1,12 @@
import * as assert from "assert";
import { Guid } from "guid-typescript";
import * as WITInterfaces from "vso-node-api/interfaces/WorkItemTrackingInterfaces";
import * as WITProcessDefinitionsInterfaces from "vso-node-api/interfaces/WorkItemTrackingProcessDefinitionsInterfaces";
import * as WITProcessInterfaces from "vso-node-api/interfaces/WorkItemTrackingProcessInterfaces";
import { IWorkItemTrackingProcessDefinitionsApi as WITProcessDefinitionApi_NOREQUIRE } from "vso-node-api/WorkItemTrackingProcessDefinitionsApi";
import { IWorkItemTrackingProcessApi as WITProcessApi_NOREQUIRE } from "vso-node-api/WorkItemTrackingProcessApi";
import { IWorkItemTrackingApi as WITApi_NOREQUIRE } from "vso-node-api/WorkItemTrackingApi";
import * as WITInterfaces from "azure-devops-node-api/interfaces/WorkItemTrackingInterfaces";
import * as WITProcessDefinitionsInterfaces from "azure-devops-node-api/interfaces/WorkItemTrackingProcessDefinitionsInterfaces";
import * as WITProcessInterfaces from "azure-devops-node-api/interfaces/WorkItemTrackingProcessInterfaces";
import { IWorkItemTrackingProcessDefinitionsApi as WITProcessDefinitionApi_NOREQUIRE } from "azure-devops-node-api/WorkItemTrackingProcessDefinitionsApi";
import { IWorkItemTrackingProcessApi as WITProcessApi_NOREQUIRE } from "azure-devops-node-api/WorkItemTrackingProcessApi";
import { IWorkItemTrackingApi as WITApi_NOREQUIRE } from "azure-devops-node-api/WorkItemTrackingApi";
import { PICKLIST_NO_ACTION } from "./Constants";
import { Engine } from "./Engine";

Просмотреть файл

@ -1,9 +1,9 @@
import * as WITInterfaces from "vso-node-api/interfaces/WorkItemTrackingInterfaces";
import * as WITProcessDefinitionsInterfaces from "vso-node-api/interfaces/WorkItemTrackingProcessDefinitionsInterfaces";
import * as WITProcessInterfaces from "vso-node-api/interfaces/WorkItemTrackingProcessInterfaces";
import * as WITInterfaces from "azure-devops-node-api/interfaces/WorkItemTrackingInterfaces";
import * as WITProcessDefinitionsInterfaces from "azure-devops-node-api/interfaces/WorkItemTrackingProcessDefinitionsInterfaces";
import * as WITProcessInterfaces from "azure-devops-node-api/interfaces/WorkItemTrackingProcessInterfaces";
import { KnownError } from "./Errors";
import { logger } from "./Logger";
import { Modes, IConfigurationFile, LogLevel } from "./Interfaces";
import { Modes, IConfigurationFile, LogLevel, ICommandLineOptions } from "./Interfaces";
import * as url from "url";
import { Guid } from "guid-typescript";
import { regexRemoveHypen } from "./Constants";
@ -193,7 +193,7 @@ export class Utility {
return false;
}
if (!configuration.targetAccountToken) {
logger.logError(`[Configuration validation] Personal access token for target account is empty.`);
logger.logError(`[Configuration validation] Missing personal access token for target account.`);
return false;
}
if (configuration.options && configuration.options.overwritePicklist && (configuration.options.overwritePicklist !== true && configuration.options.overwritePicklist !== false)) {

Просмотреть файл

@ -2,7 +2,7 @@ import { existsSync, readFileSync, writeFileSync } from "fs";
import { normalize } from "path";
import * as minimist from "minimist";
import * as url from "url";
import { defaultConfiguration, defaultConfigurationFilename, defaultEncoding, paramConfig, paramMode, paramOverwriteProcessOnTarget } from "../common/Constants";
import { defaultConfiguration, defaultConfigurationFilename, defaultEncoding, paramConfig, paramMode, paramSourceToken, paramTargetToken } from "../common/Constants";
import { IConfigurationFile, LogLevel, Modes, ICommandLineOptions } from "../common/Interfaces";
import { logger } from "../common/Logger";
import { Utility } from "../common/Utilities";
@ -14,13 +14,15 @@ export function ProcesCommandLine(): ICommandLineOptions {
alias: {
"help": "h",
"mode": "m",
"config": "c"
"config": "c",
"sourcetoken": "s",
"targettoken": "t"
}
}
const parsedArgs = minimist(process.argv, parseOptions);
if (parsedArgs["h"]) {
logger.logInfo(`Usage: processMigrator [--mode=<migrate(default)import/export> [--config=<your-configuration-file-path>]`);
logger.logInfo(`Usage: process-migrator [--mode=<migrate(default)/import/export> [--config=<your-configuration-file-path>]`);
process.exit(0);
}
@ -33,7 +35,7 @@ export function ProcesCommandLine(): ICommandLineOptions {
case Modes[Modes.export]: mode = Modes.export; break;
case Modes[Modes.import]: mode = Modes.import; break;
case Modes[Modes.migrate]: mode = Modes.migrate; break;
default: logger.logError(`Invalid mode argument, allowed values are 'import','export' and 'migrate'.`); process.exit(1);
default: logger.logError(`Invalid mode argument, allowed values are 'import', 'export' or 'migrate'.`); process.exit(1);
}
} else {
mode = Modes.migrate;
@ -42,15 +44,17 @@ export function ProcesCommandLine(): ICommandLineOptions {
const ret = {};
ret[paramMode] = mode;
ret[paramConfig] = configFileName;
ret[paramOverwriteProcessOnTarget] = !!parsedArgs[paramOverwriteProcessOnTarget];
ret[paramSourceToken] = parsedArgs[paramSourceToken];
ret[paramTargetToken] = parsedArgs[paramTargetToken];
return <ICommandLineOptions>ret;
}
export async function ProcessConfigurationFile(configFilename: string, mode: Modes): Promise<IConfigurationFile> {
export async function ProcessConfigurationFile(commandLineOptions: ICommandLineOptions): Promise<IConfigurationFile> {
// Load configuration file
if (!existsSync(configFilename)) {
logger.logError(`Cannot find configuration file '${configFilename}'`);
const configFile = commandLineOptions.config;
if (!existsSync(configFile)) {
logger.logError(`Cannot find configuration file '${configFile}'`);
const normalizedConfiguraitonFilename = normalize(defaultConfigurationFilename);
if (!existsSync(normalizedConfiguraitonFilename)) {
writeFileSync(normalizedConfiguraitonFilename, defaultConfiguration);
@ -59,8 +63,13 @@ export async function ProcessConfigurationFile(configFilename: string, mode: Mod
process.exit(1);
}
const configuration = jsoncParse(readFileSync(configFilename, defaultEncoding)) as IConfigurationFile;
if (!Utility.validateConfiguration(configuration, mode)) {
const configuration = jsoncParse(readFileSync(configFile, defaultEncoding)) as IConfigurationFile;
// replace token if overriden from command line
configuration.sourceAccountToken = commandLineOptions.sourceToken ? commandLineOptions.sourceToken : configuration.sourceAccountToken;
configuration.targetAccountToken = commandLineOptions.targetToken ? commandLineOptions.targetToken : configuration.targetAccountToken;
if (!Utility.validateConfiguration(configuration, commandLineOptions.mode)) {
process.exit(1);
}

Просмотреть файл

@ -9,7 +9,6 @@ import { logger } from "../common/Logger";
import { InitializeFileLogger } from "./FileLogger";
import { ProcessExporter } from "../common/ProcessExporter";
import { ProcessImporter } from "../common/ProcessImporter";
import { Utility } from "../common/Utilities";
import { Engine } from "../common/Engine";
import { NodeJsUtility } from "./NodeJsUtilities";
@ -20,7 +19,16 @@ async function main() {
const commandLineOptions = ProcesCommandLine();
// Read configuration file
const configuration = await ProcessConfigurationFile(commandLineOptions.config, commandLineOptions.mode)
const configuration = await ProcessConfigurationFile(commandLineOptions)
// Overwrite token if specified on command line
if (commandLineOptions.sourceToken) {
configuration.sourceAccountToken = commandLineOptions.sourceToken;
}
if (commandLineOptions.targetToken) {
configuration.targetAccountToken = commandLineOptions.targetToken;
}
// Initialize logger
const maxLogLevel = configuration.options.logLevel ? LogLevel[configuration.options.logLevel] : LogLevel.information;
@ -70,7 +78,7 @@ async function main() {
}
else {
logger.logException(error);
logger.logError(`Encourntered unkonwn error, check log file for details.`)
logger.logError(`Encountered unkonwn error, check log file for details.`)
}
process.exit(1);
}

Просмотреть файл

@ -1,4 +1,4 @@
import * as vsts from "vso-node-api/WebApi";
import * as vsts from "azure-devops-node-api/WebApi";
import { existsSync, writeFileSync } from "fs";
import { dirname, normalize } from "path";
import { sync as mkdirpSync } from "mkdirp";