├── .gitattributes ├── .github └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── .vscode ├── launch.json └── settings.json ├── LICENSE.txt ├── Tasks ├── AzureWebDeploy │ ├── Invoke-AzureWebDeploy.ps1 │ ├── README.md │ ├── icon.png │ └── task.json ├── CoverageGate │ ├── .taskkey │ ├── README.md │ ├── coverageGate.ts │ ├── icon.png │ ├── package.json │ ├── task.json │ └── yarn.lock ├── DacPacReport │ ├── DacPacReport.ps1 │ ├── FindSqlPackagePath.ps1 │ ├── TestScript.ps1 │ ├── TestXSLT.ps1 │ ├── icon.png │ ├── package.json │ ├── ps_modules │ │ └── VstsTaskSdk │ │ │ ├── FindFunctions.ps1 │ │ │ ├── InputFunctions.ps1 │ │ │ ├── LegacyFindFunctions.ps1 │ │ │ ├── LocalizationFunctions.ps1 │ │ │ ├── LoggingCommandFunctions.ps1 │ │ │ ├── LongPathFunctions.ps1 │ │ │ ├── Minimatch.dll │ │ │ ├── OutFunctions.ps1 │ │ │ ├── PSGetModuleInfo.xml │ │ │ ├── ServerOMFunctions.ps1 │ │ │ ├── Strings │ │ │ └── resources.resjson │ │ │ │ ├── de-de │ │ │ │ └── resources.resjson │ │ │ │ ├── en-US │ │ │ │ └── resources.resjson │ │ │ │ ├── es-es │ │ │ │ └── resources.resjson │ │ │ │ ├── fr-fr │ │ │ │ └── resources.resjson │ │ │ │ ├── it-IT │ │ │ │ └── resources.resjson │ │ │ │ ├── ja-jp │ │ │ │ └── resources.resjson │ │ │ │ ├── ko-KR │ │ │ │ └── resources.resjson │ │ │ │ ├── ru-RU │ │ │ │ └── resources.resjson │ │ │ │ ├── zh-CN │ │ │ │ └── resources.resjson │ │ │ │ └── zh-TW │ │ │ │ └── resources.resjson │ │ │ ├── ToolFunctions.ps1 │ │ │ ├── TraceFunctions.ps1 │ │ │ ├── VstsTaskSdk.dll │ │ │ ├── VstsTaskSdk.psd1 │ │ │ ├── VstsTaskSdk.psm1 │ │ │ └── lib.json │ ├── readme.md │ ├── report-transformToMd.xslt │ ├── task.json │ └── yarn.lock ├── DockerPublish │ ├── README.md │ ├── dockerPublish.ps1 │ ├── dockerPublishVS.ps1 │ ├── icon.png │ └── task.json ├── ReplaceTokens │ ├── .taskkey │ ├── README.md │ ├── icon.png │ ├── package.json │ ├── replaceTokens.ts │ ├── task.json │ └── yarn.lock ├── RouteTraffic │ ├── README.md │ ├── icon.png │ ├── package.json │ ├── routeTraffic.ts │ ├── task.json │ └── yarn.lock ├── TagBuild │ ├── README.md │ ├── icon.png │ ├── package.json │ ├── tagBuild.ts │ ├── task.json │ └── yarn.lock ├── Tokenizer │ ├── .taskkey │ ├── README.md │ ├── icon.png │ ├── package.json │ ├── task.json │ ├── tokenizer.ts │ └── yarn.lock └── VersionAssemblies │ ├── icon.png │ ├── package.json │ ├── readme.md │ ├── task.json │ ├── versionAssemblies.ts │ └── yarn.lock ├── Update-TaskIDs.ps1 ├── azure-pipelines.yml ├── docker └── Dockerfile ├── extension-overview.md ├── images ├── donate.png ├── extension-icon.png ├── releasePerm-security.png ├── releasePerm-set.png ├── ss_AzureWebdeploy.png ├── ss_DacPacChangeReport.png ├── ss_coverageDelta.png ├── ss_coverageGate-options.png ├── ss_coverageGate.png ├── ss_dockerPublish.png ├── ss_replaceTokens.png ├── ss_routeTraffic.png ├── ss_tagBuild.png ├── ss_tokenize.png └── ss_versionAssemblies.png ├── package.json ├── readme.md ├── taskIds.json ├── templates ├── build-job.yml └── deploy-job.yml ├── test ├── _testsuite.ts ├── coverageGate │ ├── mocks.js │ ├── mocks.ts │ ├── test-lessEqual0-fails.js │ ├── test-lessEqual0-fails.ts │ ├── test-lessThan0-succeeds.js │ ├── test-lessThan0-succeeds.ts │ ├── test-negdelta-succeeds.js │ ├── test-negdelta-succeeds.ts │ ├── test-noauth-fails.js │ ├── test-noauth-fails.ts │ ├── test-nodata-fails.js │ ├── test-nodata-fails.ts │ ├── test-nodelta-fails.js │ ├── test-nodelta-fails.ts │ ├── test-posdelta-succeeds.js │ ├── test-posdelta-succeeds.ts │ ├── test-username-succeeds.js │ └── test-username-succeeds.ts ├── replaceTokens │ ├── test-arrays.js │ ├── test-arrays.ts │ ├── test-ascii.js │ ├── test-ascii.ts │ ├── test-atTokens.js │ ├── test-atTokens.ts │ ├── test-dotTokens.js │ ├── test-dotTokens.ts │ ├── test-emptyPath.js │ ├── test-emptyPath.ts │ ├── test-normalInputs.js │ ├── test-normalInputs.ts │ ├── test-warnings-as-error-off.js │ ├── test-warnings-as-error-off.ts │ ├── test-warnings-as-errors-on.js │ ├── test-warnings-as-errors-on.ts │ └── working │ │ ├── appsettings.config │ │ ├── file.config │ │ └── file.json ├── routeTraffic │ ├── mocks.js │ ├── mocks.ts │ ├── test-handles-authFailure.js │ ├── test-handles-authFailure.ts │ ├── test-handles-callFailure.js │ ├── test-handles-callFailure.ts │ ├── test-success-forNormalInputs.js │ └── test-success-forNormalInputs.ts ├── tagBuild │ ├── mockErrorWebApi.js │ ├── mockErrorWebApi.ts │ ├── mockWebApi.js │ ├── mockWebApi.ts │ ├── test-build-noBuildId-fails.js │ ├── test-build-noBuildId-fails.ts │ ├── test-multiTag-succeeds.js │ ├── test-multiTag-succeeds.ts │ ├── test-noauth-fails.js │ ├── test-noauth-fails.ts │ ├── test-release-noReleaseId-fails.js │ ├── test-release-noReleaseId-fails.ts │ ├── test-singleTag-succeeds.js │ ├── test-singleTag-succeeds.ts │ ├── test-tagBuildFromRelease-succeeds.js │ ├── test-tagBuildFromRelease-succeeds.ts │ ├── test-tagBuildHandlesFailedCall.js │ ├── test-tagBuildHandlesFailedCall.ts │ ├── test-tagRelease-succeeds.js │ ├── test-tagRelease-succeeds.ts │ ├── test-tagReleaseHandlesFailedCall.js │ └── test-tagReleaseHandlesFailedCall.ts ├── tokenizer │ ├── test-all.js │ ├── test-all.ts │ ├── test-arrays-complex.js │ ├── test-arrays-complex.ts │ ├── test-arrays-primitive.js │ ├── test-arrays-primitive.ts │ ├── test-defaults.js │ ├── test-defaults.ts │ ├── test-dotTokens.js │ ├── test-dotTokens.ts │ ├── test-exclude.js │ ├── test-exclude.ts │ ├── test-failIfBothIncAndExcSpecified.js │ ├── test-failIfBothIncAndExcSpecified.ts │ ├── test-failsWhenNullBehaviorIsError.js │ ├── test-failsWhenNullBehaviorIsError.ts │ ├── test-trailingSlash.js │ ├── test-trailingSlash.ts │ ├── test-writesWarningForNullWhenNullBehaviorIsWarn.js │ ├── test-writesWarningForNullWhenNullBehaviorIsWarn.ts │ └── working │ │ └── appsettings.json └── versionAssemblies │ ├── test-complex.js │ ├── test-complex.ts │ ├── test-custom.js │ ├── test-custom.ts │ ├── test-defaults3.js │ ├── test-defaults3.ts │ ├── test-defaults4.js │ ├── test-defaults4.ts │ ├── test-failIfNotFound.js │ ├── test-failIfNotFound.ts │ ├── test-multiline.js │ ├── test-multiline.ts │ └── working │ ├── AndroidManifest.xml │ ├── AssemblyInfo.cs │ └── Info.plist ├── tsconfig.json ├── update-taskids.sh ├── vss-extension.json └── yarn.lock /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | schedule: 9 | - cron: '35 10 * * 6' 10 | 11 | jobs: 12 | analyze: 13 | name: Analyze 14 | runs-on: ubuntu-latest 15 | permissions: 16 | actions: read 17 | contents: read 18 | security-events: write 19 | 20 | steps: 21 | - name: Checkout repository 22 | uses: actions/checkout@v2 23 | 24 | - name: Initialize CodeQL 25 | uses: github/codeql-action/init@v1 26 | with: 27 | languages: javascript 28 | 29 | - name: Autobuild 30 | uses: github/codeql-action/autobuild@v1 31 | 32 | - name: Perform CodeQL Analysis 33 | uses: github/codeql-action/analyze@v1 34 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | // List of configurations. Add new configurations or edit existing ones. 4 | // ONLY "node" and "mono" are supported, change "type" to switch. 5 | "configurations": [ 6 | { 7 | "request": "launch", 8 | // Name of configuration; appears in the launch configuration drop down menu. 9 | "name": "Launch versionAssemblies.js", 10 | // Type of configuration. Possible values: "node", "mono". 11 | "type": "node", 12 | // Workspace relative or absolute path to the program. 13 | "program": "${workspaceRoot}/Tasks/VersionAssemblies/versionAssemblies.ts", 14 | // Automatically stop program after launch. 15 | "stopOnEntry": false, 16 | // Command line arguments passed to the program. 17 | "args": [], 18 | // Workspace relative or absolute path to the working directory of the program being debugged. Default is the current workspace. 19 | "cwd": "${workspaceRoot}", 20 | // Workspace relative or absolute path to the runtime executable to be used. Default is the runtime executable on the PATH. 21 | "runtimeExecutable": null, 22 | // Optional arguments passed to the runtime executable. 23 | "runtimeArgs": ["--nolazy"], 24 | // Environment variables passed to the program. 25 | "env": { 26 | "BUILD_BUILDNUMBER": "1.0.0.5", 27 | "INPUT_SOURCEPATH": "C:\\data\\ws\\col\\ColinsALMCornerCheckinPolicies", 28 | "INPUT_FILEPATTERN": "AssemblyInfo.*", 29 | "INPUT_BUILDREGEX": "\\d+\\.\\d+\\.\\d+\\.\\d+", 30 | "INPUT_REPLACEREGEX": "" 31 | }, 32 | // Use JavaScript source maps (if they exist). 33 | "sourceMaps": true, 34 | // If JavaScript source maps are enabled, the generated code is expected in this directory. 35 | "outDir": "${workspaceRoot}" 36 | }, 37 | { 38 | "request": "launch", 39 | "cwd": "${workspaceRoot}", 40 | "name": "Attach", 41 | "type": "node", 42 | // TCP/IP address. Default is "localhost". 43 | "address": "localhost", 44 | // Port to attach to. 45 | "port": 5858, 46 | "sourceMaps": false 47 | } 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.exclude": { 4 | "**/.git": true, 5 | "**/.svn": true, 6 | "**/.hg": true, 7 | "**/.DS_Store": true, 8 | "**/node_modules": true, 9 | "**/*.js.map": true, 10 | "**/*.js": { "when": "$(basename).ts" }, 11 | "test-results.xml": true 12 | } 13 | } -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2015 Colin Dembovsky 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. -------------------------------------------------------------------------------- /Tasks/AzureWebDeploy/README.md: -------------------------------------------------------------------------------- 1 | # Colin's ALM Corner Build Tasks - Azure Web Deploy 2 | ## DEPRECATED 3 | > The [Azure RM WebApp Deploy Task](https://github.com/Microsoft/vsts-tasks/tree/master/Tasks/AzureRmWebAppDeployment) now does everything this task does, so I'm deprecating this task. 4 | 5 | ![Azure Web Deploy Task](../../images/ss_AzureWebdeploy.png) 6 | 7 | ## Overview 8 | This task invokes Web Deploy to Azure. Use this Task over the [Azure Web App Deployment](http://go.microsoft.com/fwlink/?LinkID=613750) 9 | when you want to use tokens in the SetParameters.xml file. 10 | 11 | ## Settings 12 | The task requires the following settings: 13 | 14 | 1. **Endpoint**: An Azure Service Endpoint. This should be to the subscription that contains your Web App. 15 | 2. **Web App Name**: Name of the Web App in Azure. 16 | 3. **Web App Location**: The Azure location that the Web App is in. 17 | 4. **Slot (Optional)**: The name of the slot that you are publishing the Web App to. Leave empty for no slot. 18 | 5. **Package Path**: The path to the folder containing the webdeploy zip file, cmd file and SetParameters.xml file. 19 | 20 | ## Token Replacement 21 | You should use the [Replace Tokens](..\ReplaceTokens\README.md) task in order to perform token replacement prior to this task. For more information, 22 | see this [blog post](http://colinsalmcorner.com/post/webdeploy-configs-and-web-release-management). 23 | -------------------------------------------------------------------------------- /Tasks/AzureWebDeploy/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/Tasks/AzureWebDeploy/icon.png -------------------------------------------------------------------------------- /Tasks/CoverageGate/.taskkey: -------------------------------------------------------------------------------- 1 | f2bfe5f0-ad45-11e6-ab7a-d1ca80fbcd65 -------------------------------------------------------------------------------- /Tasks/CoverageGate/README.md: -------------------------------------------------------------------------------- 1 | # Colin's ALM Corner Build Tasks - Coverage Gate 2 | 3 | ![Coverage Gate Task](../../images/ss_coverageGate.png) 4 | 5 | ## Overview 6 | This task allows you to fail a build/release if the build coverage delta is below a defined threshold. 7 | 8 | The build coverage delta is the delta between the coverage percentage of "this" build compared to the 9 | previous successful build. If the delta is negative, coverage is less. You can see the coverage delta 10 | in the build report under the `Coverage` section: 11 | 12 | ![Coverage Delta](../../images/ss_coverageDelta.png) 13 | 14 | When applying this task to a release, the release gets the build linked to the release and calculates 15 | the delta from the previous build (using the VSTS/TFS API). It then compares the delta to the threshold 16 | setting for the task. 17 | 18 | ![Coverage Gate options](../../images/ss_coverageGate-options.png) 19 | 20 | To stop (fail) a release if the coverage has not incremented (improved), simply set the threshold to 0 21 | and set the operator to `<=`. If you want to just enforce that the coverage has not decreased, then set 22 | the threshold to 0 and the operator to `<`. You can of course use other values if you choose to. 23 | 24 | ## Authentication 25 | This task will try to use the OAuth token from the build/release. You must enable this option in the 26 | build/release options. For VSTS/TFS builds, this setting is in the options page. 27 | 28 | For VSTS releases, this is set on the release agent settings for each environment. For TFS 2015 Update 3, 29 | unfortunately this switch is not available on releases and you cannot create a PAT, so you'll have to 30 | enter a username/password for the task in the `TFS 2015` section. (Please be responsible and use a secret 31 | for the password!) -------------------------------------------------------------------------------- /Tasks/CoverageGate/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/Tasks/CoverageGate/icon.png -------------------------------------------------------------------------------- /Tasks/CoverageGate/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "colinsalmcornerbuildtaskscoveragetrend", 3 | "version": "0.0.3", 4 | "description": "Generates a code coverage trend attachment for build summaries", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/colindembovsky/cols-agent-tasks" 11 | }, 12 | "keywords": [ 13 | "VSO", 14 | "build", 15 | "tasks", 16 | "coverage" 17 | ], 18 | "author": "Colin Dembovsky (ColinsALMCorner.com)", 19 | "license": "MIT", 20 | "bugs": { 21 | "url": "https://github.com/colindembovsky/cols-agent-tasks/issues" 22 | }, 23 | "homepage": "https://github.com/colindembovsky/cols-agent-tasks", 24 | "dependencies": { 25 | "azure-devops-node-api": "^14.1.0", 26 | "azure-pipelines-task-lib": "4.17.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Tasks/CoverageGate/task.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "0b6f0167-8389-4db8-89c6-4ae7688cd15a", 3 | "name": "CoverageGate", 4 | "friendlyName": "Coverage Gate", 5 | "description": "Adds a coverage trend summary section to the build report.", 6 | "author": "Colin Dembovsky (colinsalmcorner.com)", 7 | "helpMarkDown": "[More Information](https://github.com/colindembovsky/cols-agent-tasks/tree/master/Tasks/CoverageGate)", 8 | "category": "Utility", 9 | "visibility": [ 10 | "Build", 11 | "Release" 12 | ], 13 | "version": { 14 | "Major": "1", 15 | "Minor": "2", 16 | "Patch": "9" 17 | }, 18 | "minimumAgentVersion": "1.91.0", 19 | "instanceNameFormat": "Fail if coverage delta is below $(minDelta)", 20 | "groups": [ 21 | { 22 | "name": "2015", 23 | "displayName": "TFS 2015", 24 | "isExpanded": false 25 | } 26 | ], 27 | "inputs": [ 28 | { 29 | "name": "minDelta", 30 | "type": "string", 31 | "label": "Delta", 32 | "defaultValue": "0", 33 | "helpMarkDown": "Fail if the coverage delta is below this value.", 34 | "required": true 35 | }, 36 | { 37 | "name": "operator", 38 | "type": "pickList", 39 | "label": "Operator", 40 | "defaultValue": "lt", 41 | "helpMarkDown": "Operator to apply. Either < or <=", 42 | "required": true, 43 | "options": { 44 | "le": "<=", 45 | "lt": "<" 46 | } 47 | }, 48 | { 49 | "name": "username", 50 | "type": "string", 51 | "label": "Username", 52 | "helpMarkDown": "Username to access TFS - only required for TFS 2015.3 or earlier, where OAuth", 53 | "required": false, 54 | "groupName": "2015" 55 | }, 56 | { 57 | "name": "password", 58 | "type": "string", 59 | "label": "Password", 60 | "helpMarkDown": "Password to access TFS", 61 | "required": false, 62 | "groupName": "2015" 63 | } 64 | ], 65 | "execution": { 66 | "Node10": { 67 | "target": "coverageGate.js", 68 | "argumentFormat": "" 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Tasks/DacPacReport/TestScript.ps1: -------------------------------------------------------------------------------- 1 | # 2 | # DEBUGGING: 3 | # 1. clone the azure-pipelines-task-lib to the same level as cols-agent-tasks 4 | # Import-Module ..\..\..\azure-pipelines-task-lib\powershell\VstsTaskSdk -ArgumentList @{ NonInteractive = $true } -Verbose:$true 5 | # 3. Invoke this script 6 | # 7 | 8 | param( 9 | [string]$pat = (Read-Host -Prompt "PAT") 10 | ) 11 | 12 | $vstsAcc = "cacdemo" 13 | $rootUri = "https://$vstsAcc.visualstudio.com/" 14 | 15 | $base64authinfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f "", $pat))) 16 | 17 | Import-Module .\ps_modules\VstsTaskSdk -ArgumentList @{ NonInteractive = $true } -Verbose:$true 18 | 19 | # system variables 20 | $env:SYSTEM_ACCESSTOKEN=$base64authinfo 21 | $env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI=$rootUri 22 | $env:SYSTEM_TEAMPROJECTID="ec235bcd-730b-442e-bd5d-b63437c1cb7c" # cacdemo/Demo 23 | $env:SYSTEM_DEFINITIONID=9 # FabFiberExpress-DACPAC 24 | 25 | # user inputs 26 | $env:INPUT_DROPNAME="drop" 27 | $env:INPUT_DACPACNAME="fabFiber.Schema" 28 | $env:INPUT_TARGETDACPACPATH="C:\mData\ws\col\dac" 29 | $env:INPUT_EXTRAARGS="/v:Hello=Bye" 30 | #$env:INPUT_USERSQLPACKAGEPATH="c:\foo\foo.exe" 31 | 32 | # invoke the script 33 | Invoke-VstsTaskScript -ScriptBlock ([scriptblock]::Create('. .\DacPacReport.ps1')) -Verbose -------------------------------------------------------------------------------- /Tasks/DacPacReport/TestXSLT.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/Tasks/DacPacReport/TestXSLT.ps1 -------------------------------------------------------------------------------- /Tasks/DacPacReport/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/Tasks/DacPacReport/icon.png -------------------------------------------------------------------------------- /Tasks/DacPacReport/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "colinsalmcornerbuildtasksdacpacreport", 3 | "version": "0.0.1", 4 | "description": "Provides a report on database model changes since the last build", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/colindembovsky/cols-agent-tasks" 11 | }, 12 | "keywords": [ 13 | "VSO", 14 | "build", 15 | "dacpac" 16 | ], 17 | "author": "Colin Dembovsky (ColinsALMCorner.com)", 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/colindembovsky/cols-agent-tasks/issues" 21 | }, 22 | "homepage": "https://github.com/colindembovsky/cols-agent-tasks", 23 | "devDependencies": { 24 | "azure-pipelines-task-lib": "3.1.10", 25 | "libxslt": "^0.10.2", 26 | "minimatch": "^3.0.4", 27 | "shelljs": "^0.8.5" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Tasks/DacPacReport/ps_modules/VstsTaskSdk/Minimatch.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/Tasks/DacPacReport/ps_modules/VstsTaskSdk/Minimatch.dll -------------------------------------------------------------------------------- /Tasks/DacPacReport/ps_modules/VstsTaskSdk/PSGetModuleInfo.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/Tasks/DacPacReport/ps_modules/VstsTaskSdk/PSGetModuleInfo.xml -------------------------------------------------------------------------------- /Tasks/DacPacReport/ps_modules/VstsTaskSdk/Strings/resources.resjson/de-de/resources.resjson: -------------------------------------------------------------------------------- 1 | { 2 | "loc.messages.PSLIB_AgentVersion0Required": "Agentversion {0} oder höher ist erforderlich.", 3 | "loc.messages.PSLIB_ContainerPathNotFound0": "Der Containerpfad wurde nicht gefunden: \"{0}\".", 4 | "loc.messages.PSLIB_EndpointAuth0": "\"{0}\"-Dienstendpunkt-Anmeldeinformationen", 5 | "loc.messages.PSLIB_EndpointUrl0": "\"{0}\"-Dienstendpunkt-URL", 6 | "loc.messages.PSLIB_EnumeratingSubdirectoriesFailedForPath0": "Fehler beim Aufzählen von Unterverzeichnissen für den folgenden Pfad: \"{0}\"", 7 | "loc.messages.PSLIB_FileNotFound0": "Die Datei wurde nicht gefunden: \"{0}\".", 8 | "loc.messages.PSLIB_Input0": "\"{0}\"-Eingabe", 9 | "loc.messages.PSLIB_InvalidPattern0": "Ungültiges Muster: \"{0}\"", 10 | "loc.messages.PSLIB_LeafPathNotFound0": "Der Blattpfad wurde nicht gefunden: \"{0}\".", 11 | "loc.messages.PSLIB_PathLengthNotReturnedFor0": "Fehler bei der Normalisierung bzw. Erweiterung des Pfads. Die Pfadlänge wurde vom Kernel32-Subsystem nicht zurückgegeben für: \"{0}\"", 12 | "loc.messages.PSLIB_PathNotFound0": "Der Pfad wurde nicht gefunden: \"{0}\".", 13 | "loc.messages.PSLIB_Process0ExitedWithCode1": "Der Prozess \"{0}\" wurde mit dem Code \"{1}\" beendet.", 14 | "loc.messages.PSLIB_Required0": "Erforderlich: {0}", 15 | "loc.messages.PSLIB_StringFormatFailed": "Fehler beim Zeichenfolgenformat.", 16 | "loc.messages.PSLIB_StringResourceKeyNotFound0": "Der Zeichenfolgen-Ressourcenschlüssel wurde nicht gefunden: \"{0}\".", 17 | "loc.messages.PSLIB_TaskVariable0": "\"{0}\"-Taskvariable" 18 | } -------------------------------------------------------------------------------- /Tasks/DacPacReport/ps_modules/VstsTaskSdk/Strings/resources.resjson/en-US/resources.resjson: -------------------------------------------------------------------------------- 1 | { 2 | "loc.messages.PSLIB_AgentVersion0Required": "Agent version {0} or higher is required.", 3 | "loc.messages.PSLIB_ContainerPathNotFound0": "Container path not found: '{0}'", 4 | "loc.messages.PSLIB_EndpointAuth0": "'{0}' service endpoint credentials", 5 | "loc.messages.PSLIB_EndpointUrl0": "'{0}' service endpoint URL", 6 | "loc.messages.PSLIB_EnumeratingSubdirectoriesFailedForPath0": "Enumerating subdirectories failed for path: '{0}'", 7 | "loc.messages.PSLIB_FileNotFound0": "File not found: '{0}'", 8 | "loc.messages.PSLIB_Input0": "'{0}' input", 9 | "loc.messages.PSLIB_InvalidPattern0": "Invalid pattern: '{0}'", 10 | "loc.messages.PSLIB_LeafPathNotFound0": "Leaf path not found: '{0}'", 11 | "loc.messages.PSLIB_PathLengthNotReturnedFor0": "Path normalization/expansion failed. The path length was not returned by the Kernel32 subsystem for: '{0}'", 12 | "loc.messages.PSLIB_PathNotFound0": "Path not found: '{0}'", 13 | "loc.messages.PSLIB_Process0ExitedWithCode1": "Process '{0}' exited with code '{1}'.", 14 | "loc.messages.PSLIB_Required0": "Required: {0}", 15 | "loc.messages.PSLIB_StringFormatFailed": "String format failed.", 16 | "loc.messages.PSLIB_StringResourceKeyNotFound0": "String resource key not found: '{0}'", 17 | "loc.messages.PSLIB_TaskVariable0": "'{0}' task variable" 18 | } -------------------------------------------------------------------------------- /Tasks/DacPacReport/ps_modules/VstsTaskSdk/Strings/resources.resjson/es-es/resources.resjson: -------------------------------------------------------------------------------- 1 | { 2 | "loc.messages.PSLIB_AgentVersion0Required": "Se require la versión {0} o posterior del agente.", 3 | "loc.messages.PSLIB_ContainerPathNotFound0": "No se encuentra la ruta de acceso del contenedor: '{0}'", 4 | "loc.messages.PSLIB_EndpointAuth0": "Credenciales del punto de conexión de servicio '{0}'", 5 | "loc.messages.PSLIB_EndpointUrl0": "URL del punto de conexión de servicio '{0}'", 6 | "loc.messages.PSLIB_EnumeratingSubdirectoriesFailedForPath0": "No se pudieron enumerar los subdirectorios de la ruta de acceso: '{0}'", 7 | "loc.messages.PSLIB_FileNotFound0": "Archivo no encontrado: '{0}'", 8 | "loc.messages.PSLIB_Input0": "Entrada '{0}'", 9 | "loc.messages.PSLIB_InvalidPattern0": "Patrón no válido: '{0}'", 10 | "loc.messages.PSLIB_LeafPathNotFound0": "No se encuentra la ruta de acceso de la hoja: '{0}'", 11 | "loc.messages.PSLIB_PathLengthNotReturnedFor0": "No se pudo normalizar o expandir la ruta de acceso. El subsistema Kernel32 no devolvió la longitud de la ruta de acceso para: '{0}'", 12 | "loc.messages.PSLIB_PathNotFound0": "No se encuentra la ruta de acceso: '{0}'", 13 | "loc.messages.PSLIB_Process0ExitedWithCode1": "El proceso '{0}' finalizó con el código '{1}'.", 14 | "loc.messages.PSLIB_Required0": "Se requiere: {0}", 15 | "loc.messages.PSLIB_StringFormatFailed": "Error de formato de cadena.", 16 | "loc.messages.PSLIB_StringResourceKeyNotFound0": "No se encuentra la clave de recurso de la cadena: '{0}'", 17 | "loc.messages.PSLIB_TaskVariable0": "Variable de tarea '{0}'" 18 | } -------------------------------------------------------------------------------- /Tasks/DacPacReport/ps_modules/VstsTaskSdk/Strings/resources.resjson/fr-fr/resources.resjson: -------------------------------------------------------------------------------- 1 | { 2 | "loc.messages.PSLIB_AgentVersion0Required": "L'agent version {0} (ou une version ultérieure) est obligatoire.", 3 | "loc.messages.PSLIB_ContainerPathNotFound0": "Le chemin du conteneur est introuvable : '{0}'", 4 | "loc.messages.PSLIB_EndpointAuth0": "Informations d'identification du point de terminaison de service '{0}'", 5 | "loc.messages.PSLIB_EndpointUrl0": "URL du point de terminaison de service '{0}'", 6 | "loc.messages.PSLIB_EnumeratingSubdirectoriesFailedForPath0": "Échec de l'énumération des sous-répertoires pour le chemin : '{0}'", 7 | "loc.messages.PSLIB_FileNotFound0": "Fichier introuvable : {0}.", 8 | "loc.messages.PSLIB_Input0": "Entrée '{0}'", 9 | "loc.messages.PSLIB_InvalidPattern0": "Modèle non valide : '{0}'", 10 | "loc.messages.PSLIB_LeafPathNotFound0": "Le chemin feuille est introuvable : '{0}'", 11 | "loc.messages.PSLIB_PathLengthNotReturnedFor0": "Échec de la normalisation/l'expansion du chemin. La longueur du chemin n'a pas été retournée par le sous-système Kernel32 pour : '{0}'", 12 | "loc.messages.PSLIB_PathNotFound0": "Chemin introuvable : '{0}'", 13 | "loc.messages.PSLIB_Process0ExitedWithCode1": "Le processus '{0}' s'est arrêté avec le code '{1}'.", 14 | "loc.messages.PSLIB_Required0": "Obligatoire : {0}", 15 | "loc.messages.PSLIB_StringFormatFailed": "Échec du format de la chaîne.", 16 | "loc.messages.PSLIB_StringResourceKeyNotFound0": "Clé de la ressource de type chaîne introuvable : '{0}'", 17 | "loc.messages.PSLIB_TaskVariable0": "Variable de tâche '{0}'" 18 | } -------------------------------------------------------------------------------- /Tasks/DacPacReport/ps_modules/VstsTaskSdk/Strings/resources.resjson/it-IT/resources.resjson: -------------------------------------------------------------------------------- 1 | { 2 | "loc.messages.PSLIB_AgentVersion0Required": "È richiesta la versione dell'agente {0} o superiore.", 3 | "loc.messages.PSLIB_ContainerPathNotFound0": "Percorso del contenitore non trovato: '{0}'", 4 | "loc.messages.PSLIB_EndpointAuth0": "Credenziali dell'endpoint servizio '{0}'", 5 | "loc.messages.PSLIB_EndpointUrl0": "URL dell'endpoint servizio '{0}'", 6 | "loc.messages.PSLIB_EnumeratingSubdirectoriesFailedForPath0": "L'enumerazione delle sottodirectory per il percorso '{0}' non è riuscita", 7 | "loc.messages.PSLIB_FileNotFound0": "File non trovato: '{0}'", 8 | "loc.messages.PSLIB_Input0": "Input di '{0}'", 9 | "loc.messages.PSLIB_InvalidPattern0": "Criterio non valido: '{0}'", 10 | "loc.messages.PSLIB_LeafPathNotFound0": "Percorso foglia non trovato: '{0}'", 11 | "loc.messages.PSLIB_PathLengthNotReturnedFor0": "La normalizzazione o l'espansione del percorso non è riuscita. Il sottosistema Kernel32 non ha restituito la lunghezza del percorso per '{0}'", 12 | "loc.messages.PSLIB_PathNotFound0": "Percorso non trovato: '{0}'", 13 | "loc.messages.PSLIB_Process0ExitedWithCode1": "Il processo '{0}' è stato terminato ed è stato restituito il codice '{1}'.", 14 | "loc.messages.PSLIB_Required0": "Obbligatorio: {0}", 15 | "loc.messages.PSLIB_StringFormatFailed": "Errore nel formato della stringa.", 16 | "loc.messages.PSLIB_StringResourceKeyNotFound0": "La chiave della risorsa stringa non è stata trovata: '{0}'", 17 | "loc.messages.PSLIB_TaskVariable0": "Variabile dell'attività '{0}'" 18 | } -------------------------------------------------------------------------------- /Tasks/DacPacReport/ps_modules/VstsTaskSdk/Strings/resources.resjson/ja-jp/resources.resjson: -------------------------------------------------------------------------------- 1 | { 2 | "loc.messages.PSLIB_AgentVersion0Required": "バージョン {0} 以降のエージェントが必要です。", 3 | "loc.messages.PSLIB_ContainerPathNotFound0": "コンテナーのパスが見つかりません: '{0}'", 4 | "loc.messages.PSLIB_EndpointAuth0": "'{0}' サービス エンドポイントの資格情報", 5 | "loc.messages.PSLIB_EndpointUrl0": "'{0}' サービス エンドポイントの URL", 6 | "loc.messages.PSLIB_EnumeratingSubdirectoriesFailedForPath0": "パス '{0}' のサブディレクトリを列挙できませんでした", 7 | "loc.messages.PSLIB_FileNotFound0": "ファイルが見つかりません: '{0}'", 8 | "loc.messages.PSLIB_Input0": "'{0}' 入力", 9 | "loc.messages.PSLIB_InvalidPattern0": "使用できないパターンです: '{0}'", 10 | "loc.messages.PSLIB_LeafPathNotFound0": "リーフ パスが見つかりません: '{0}'", 11 | "loc.messages.PSLIB_PathLengthNotReturnedFor0": "パスの正規化/展開に失敗しました。Kernel32 サブシステムからパス '{0}' の長さが返されませんでした", 12 | "loc.messages.PSLIB_PathNotFound0": "パスが見つかりません: '{0}'", 13 | "loc.messages.PSLIB_Process0ExitedWithCode1": "プロセス '{0}' がコード '{1}' で終了しました。", 14 | "loc.messages.PSLIB_Required0": "必要: {0}", 15 | "loc.messages.PSLIB_StringFormatFailed": "文字列のフォーマットに失敗しました。", 16 | "loc.messages.PSLIB_StringResourceKeyNotFound0": "文字列のリソース キーが見つかりません: '{0}'", 17 | "loc.messages.PSLIB_TaskVariable0": "'{0}' タスク変数" 18 | } -------------------------------------------------------------------------------- /Tasks/DacPacReport/ps_modules/VstsTaskSdk/Strings/resources.resjson/ko-KR/resources.resjson: -------------------------------------------------------------------------------- 1 | { 2 | "loc.messages.PSLIB_AgentVersion0Required": "에이전트 버전 {0} 이상이 필요합니다.", 3 | "loc.messages.PSLIB_ContainerPathNotFound0": "컨테이너 경로를 찾을 수 없음: '{0}'", 4 | "loc.messages.PSLIB_EndpointAuth0": "'{0}' 서비스 끝점 자격 증명", 5 | "loc.messages.PSLIB_EndpointUrl0": "'{0}' 서비스 끝점 URL", 6 | "loc.messages.PSLIB_EnumeratingSubdirectoriesFailedForPath0": "경로에 대해 하위 디렉터리를 열거하지 못함: '{0}'", 7 | "loc.messages.PSLIB_FileNotFound0": "{0} 파일을 찾을 수 없습니다.", 8 | "loc.messages.PSLIB_Input0": "'{0}' 입력", 9 | "loc.messages.PSLIB_InvalidPattern0": "잘못된 패턴: '{0}'", 10 | "loc.messages.PSLIB_LeafPathNotFound0": "Leaf 경로를 찾을 수 없음: '{0}'", 11 | "loc.messages.PSLIB_PathLengthNotReturnedFor0": "경로 정규화/확장에 실패했습니다. 다음에 대해 Kernel32 subsystem에서 경로 길이를 반환하지 않음: '{0}'", 12 | "loc.messages.PSLIB_PathNotFound0": "경로를 찾을 수 없음: '{0}'", 13 | "loc.messages.PSLIB_Process0ExitedWithCode1": "'{1}' 코드로 '{0}' 프로세스가 종료되었습니다.", 14 | "loc.messages.PSLIB_Required0": "필수: {0}", 15 | "loc.messages.PSLIB_StringFormatFailed": "문자열을 포맷하지 못했습니다.", 16 | "loc.messages.PSLIB_StringResourceKeyNotFound0": "문자열 리소스 키를 찾을 수 없음: '{0}'", 17 | "loc.messages.PSLIB_TaskVariable0": "'{0}' 작업 변수" 18 | } -------------------------------------------------------------------------------- /Tasks/DacPacReport/ps_modules/VstsTaskSdk/Strings/resources.resjson/ru-RU/resources.resjson: -------------------------------------------------------------------------------- 1 | { 2 | "loc.messages.PSLIB_AgentVersion0Required": "Требуется версия агента {0} или более поздняя.", 3 | "loc.messages.PSLIB_ContainerPathNotFound0": "Путь к контейнеру не найден: \"{0}\".", 4 | "loc.messages.PSLIB_EndpointAuth0": "Учетные данные конечной точки службы \"{0}\"", 5 | "loc.messages.PSLIB_EndpointUrl0": "URL-адрес конечной точки службы \"{0}\"", 6 | "loc.messages.PSLIB_EnumeratingSubdirectoriesFailedForPath0": "Сбой перечисления подкаталогов для пути: \"{0}\".", 7 | "loc.messages.PSLIB_FileNotFound0": "Файл не найден: \"{0}\".", 8 | "loc.messages.PSLIB_Input0": "Входные данные \"{0}\".", 9 | "loc.messages.PSLIB_InvalidPattern0": "Недопустимый шаблон: \"{0}\".", 10 | "loc.messages.PSLIB_LeafPathNotFound0": "Путь к конечному объекту не найден: \"{0}\".", 11 | "loc.messages.PSLIB_PathLengthNotReturnedFor0": "Сбой нормализации и расширения пути. Длина пути не была возвращена подсистемой Kernel32 для: \"{0}\".", 12 | "loc.messages.PSLIB_PathNotFound0": "Путь не найден: \"{0}\".", 13 | "loc.messages.PSLIB_Process0ExitedWithCode1": "Процесс \"{0}\" завершил работу с кодом \"{1}\".", 14 | "loc.messages.PSLIB_Required0": "Требуется: {0}", 15 | "loc.messages.PSLIB_StringFormatFailed": "Сбой формата строки.", 16 | "loc.messages.PSLIB_StringResourceKeyNotFound0": "Ключ ресурса строки не найден: \"{0}\".", 17 | "loc.messages.PSLIB_TaskVariable0": "Переменная задачи \"{0}\"" 18 | } -------------------------------------------------------------------------------- /Tasks/DacPacReport/ps_modules/VstsTaskSdk/Strings/resources.resjson/zh-CN/resources.resjson: -------------------------------------------------------------------------------- 1 | { 2 | "loc.messages.PSLIB_AgentVersion0Required": "需要代理版本 {0} 或更高版本。", 3 | "loc.messages.PSLIB_ContainerPathNotFound0": "找不到容器路径:“{0}”", 4 | "loc.messages.PSLIB_EndpointAuth0": "“{0}”服务终结点凭据", 5 | "loc.messages.PSLIB_EndpointUrl0": "“{0}”服务终结点 URL", 6 | "loc.messages.PSLIB_EnumeratingSubdirectoriesFailedForPath0": "枚举路径的子目录失败:“{0}”", 7 | "loc.messages.PSLIB_FileNotFound0": "找不到文件: {0}。", 8 | "loc.messages.PSLIB_Input0": "“{0}”输入", 9 | "loc.messages.PSLIB_InvalidPattern0": "无效的模式:“{0}”", 10 | "loc.messages.PSLIB_LeafPathNotFound0": "找不到叶路径:“{0}”", 11 | "loc.messages.PSLIB_PathLengthNotReturnedFor0": "路径规范化/扩展失败。路径长度不是由“{0}”的 Kernel32 子系统返回的", 12 | "loc.messages.PSLIB_PathNotFound0": "找不到路径:“{0}”", 13 | "loc.messages.PSLIB_Process0ExitedWithCode1": "过程“{0}”已退出,代码为“{1}”。", 14 | "loc.messages.PSLIB_Required0": "必需: {0}", 15 | "loc.messages.PSLIB_StringFormatFailed": "字符串格式无效。", 16 | "loc.messages.PSLIB_StringResourceKeyNotFound0": "找不到字符串资源关键字:“{0}”", 17 | "loc.messages.PSLIB_TaskVariable0": "“{0}”任务变量" 18 | } -------------------------------------------------------------------------------- /Tasks/DacPacReport/ps_modules/VstsTaskSdk/Strings/resources.resjson/zh-TW/resources.resjson: -------------------------------------------------------------------------------- 1 | { 2 | "loc.messages.PSLIB_AgentVersion0Required": "需要代理程式版本 {0} 或更新的版本。", 3 | "loc.messages.PSLIB_ContainerPathNotFound0": "找不到容器路徑: '{0}'", 4 | "loc.messages.PSLIB_EndpointAuth0": "'{0}' 服務端點認證", 5 | "loc.messages.PSLIB_EndpointUrl0": "'{0}' 服務端點 URL", 6 | "loc.messages.PSLIB_EnumeratingSubdirectoriesFailedForPath0": "為路徑列舉子目錄失敗: '{0}'", 7 | "loc.messages.PSLIB_FileNotFound0": "找不到檔案: '{0}'", 8 | "loc.messages.PSLIB_Input0": "'{0}' 輸入", 9 | "loc.messages.PSLIB_InvalidPattern0": "模式無效: '{0}'", 10 | "loc.messages.PSLIB_LeafPathNotFound0": "找不到分葉路徑: '{0}'", 11 | "loc.messages.PSLIB_PathLengthNotReturnedFor0": "路徑正規化/展開失敗。Kernel32 子系統未傳回 '{0}' 的路徑長度", 12 | "loc.messages.PSLIB_PathNotFound0": "找不到路徑: '{0}'", 13 | "loc.messages.PSLIB_Process0ExitedWithCode1": "處理序 '{0}' 以返回碼 '{1}' 結束。", 14 | "loc.messages.PSLIB_Required0": "必要項: {0}", 15 | "loc.messages.PSLIB_StringFormatFailed": "字串格式失敗。", 16 | "loc.messages.PSLIB_StringResourceKeyNotFound0": "找不到字串資源索引鍵: '{0}'", 17 | "loc.messages.PSLIB_TaskVariable0": "'{0}' 工作變數" 18 | } -------------------------------------------------------------------------------- /Tasks/DacPacReport/ps_modules/VstsTaskSdk/VstsTaskSdk.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/Tasks/DacPacReport/ps_modules/VstsTaskSdk/VstsTaskSdk.dll -------------------------------------------------------------------------------- /Tasks/DacPacReport/ps_modules/VstsTaskSdk/VstsTaskSdk.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/Tasks/DacPacReport/ps_modules/VstsTaskSdk/VstsTaskSdk.psd1 -------------------------------------------------------------------------------- /Tasks/DacPacReport/ps_modules/VstsTaskSdk/lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "messages": { 3 | "PSLIB_AgentVersion0Required": "Agent version {0} or higher is required.", 4 | "PSLIB_ContainerPathNotFound0": "Container path not found: '{0}'", 5 | "PSLIB_EndpointAuth0": "'{0}' service endpoint credentials", 6 | "PSLIB_EndpointUrl0": "'{0}' service endpoint URL", 7 | "PSLIB_EnumeratingSubdirectoriesFailedForPath0": "Enumerating subdirectories failed for path: '{0}'", 8 | "PSLIB_FileNotFound0": "File not found: '{0}'", 9 | "PSLIB_Input0": "'{0}' input", 10 | "PSLIB_InvalidPattern0": "Invalid pattern: '{0}'", 11 | "PSLIB_LeafPathNotFound0": "Leaf path not found: '{0}'", 12 | "PSLIB_PathLengthNotReturnedFor0": "Path normalization/expansion failed. The path length was not returned by the Kernel32 subsystem for: '{0}'", 13 | "PSLIB_PathNotFound0": "Path not found: '{0}'", 14 | "PSLIB_Process0ExitedWithCode1": "Process '{0}' exited with code '{1}'.", 15 | "PSLIB_Required0": "Required: {0}", 16 | "PSLIB_StringFormatFailed": "String format failed.", 17 | "PSLIB_StringResourceKeyNotFound0": "String resource key not found: '{0}'", 18 | "PSLIB_TaskVariable0": "'{0}' task variable" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Tasks/DacPacReport/readme.md: -------------------------------------------------------------------------------- 1 | # Colin's ALM Corner Build Tasks - DacPac Change Report 2 | 3 | ![DacPac Change Report Task](../../images/ss_DacPacChangeReport.png) 4 | 5 | ## YAML 6 | ```yaml 7 | steps: 8 | - task: colinsalmcorner.colinsalmcorner-buildtasksbeta.dacpac-report-task.DacPacReport@1 9 | displayName: 'DacPac Schema Compare MyDBProject.dacpac' 10 | inputs: 11 | # dropName: drop # name of the published artifact that contains the dacpac for the build: the dacpac is downloaded from this drop. 12 | dacpacName: MyDBProject # name of the dacpac (without extension) to compare 13 | targetDacPacPath: MyDBProject\bin\$(BuildConfiguration) # Path to dacpac in this build (to compare to output of previous build) 14 | # extraArgs: '/Variables myvar=myvalue' # extra args for the compare - use to supply SQLCMD variables, for example. 15 | # reverse: false # set to true to reverse source and target for compare 16 | # userSqlPackagePath: '' # the sqlpackage.exe filepath - use this only if the default does not detect the path correctly 17 | ``` 18 | 19 | ## Overview 20 | This task shows the schema changes of a DacPac between builds. The task adds two sections to the build summary: 21 | 1. **Schema Change Summary**: A summary of changes from the last build. 22 | 1. **Change Script**: The SQL-CMD script that would be generated if deploying from the newer dacpac model against the older model. 23 | 24 | ## Settings 25 | The task requires the following settings: 26 | 27 | 1. **Drop Name**: The drop name of the build that contains the dacpac file. You must publish the dacpac for this task to work. 28 | 1. **DacPac Name**: Name of the DacPac to analyze (without .dacpac extension). 29 | 1. **Compiled DacPac Path**: Path to the DacPac file that this build will produce. Typically the `bin\$(BuildConfiguration)` path of the SSDT project. 30 | 31 | ## OAuth Token 32 | You must enable `Allow Scripts to Access OAuth Token` on the build Options. If you do not, you will see 403 errors. 33 | -------------------------------------------------------------------------------- /Tasks/DacPacReport/report-transformToMd.xslt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ## Errors 7 | 8 | - 9 | 10 | 11 | 12 | 13 | ## Warnings 14 | 15 | - 16 | 17 | 18 | 19 | 20 | ## Alerts 21 | 22 | ### 23 | 24 | - 25 | 26 | 27 | 28 | 29 | 30 | ## Operations 31 | 32 | ### 33 | 34 | - `` 35 | 36 | 37 | 38 | 39 | 40 | 41 | No changes - models are identical. 42 | 43 | 44 | 45 | 46 | 47 | ]]> ****: __ 48 | 49 | 50 | -------------------------------------------------------------------------------- /Tasks/DockerPublish/README.md: -------------------------------------------------------------------------------- 1 | # Colin's ALM Corner Build Tasks - Docker Publish 2 | ## DEPRECATED 3 | > The [Docker Integration Extension](https://marketplace.visualstudio.com/items?itemName=ms-vscs-rm.docker) is finally fully featured, so I'm deprecating this task. 4 | 5 | ![Docker Publish Task](../../images/ss_dockerPublish.png) 6 | 7 | ## Overview 8 | This task deploys code to a docker image (and optionally runs a container). You can use a pubxml generated by [VS Tools for Docker](https://visualstudiogallery.msdn.microsoft.com/0f5b2caa-ea00-41c8-b8a2-058c7da0b3e4) or just supply all the settings manually. 9 | 10 | ## Settings 11 | The task has the following settings: 12 | 13 | 1. **Path to Pubxml file**: path in the repo to the pubxml file (optional) 14 | 2. **Path to Dockerfile**: (required) path to the Dockerfile 15 | 3. **Pack Output Path**: (required) path to the root of the files you want to deploy to the container 16 | 4. **Docker Server Url**: url of your docker host 17 | 5. **Docker image name**: name of the image to build 18 | 6. **Build Only**: true to just run "docker build": false if you want to execute "docker run" after building 19 | 7. **Host port**: the port to open on the host 20 | 5. **Container port**: the port to open on the container 21 | 8. **Run options**: additional arguments passed to the "docker run" command 22 | 9. **App Type**: can be empty or "Web". Only required for ASP.NET applications (sets the _server.urls_ setting) 23 | 10. **Create Windows Container**: set to "true" if you're targeting a Windows docker host 24 | 11. **Auth Options**: additional arguments to supply to docker commands (for example --tlscert) 25 | 12. **Remove Conflicting Containers**: removes containers currently running on the same port when set to "true" 26 | 27 | ## Details 28 | For a more detailed look at this task (and how to use it for ASP.NET 5 applications) read [this post](http://colinsalmcorner.com/post/continuous-deployment-with-docker-and-build-vnext). 29 | -------------------------------------------------------------------------------- /Tasks/DockerPublish/dockerPublish.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [string]$pathToPubxml, 3 | [string]$pathToDockerfile, 4 | [string]$packOutput, 5 | [string]$serverUrl, 6 | [string]$imageName, 7 | [string]$hostPort, 8 | [string]$containerPort, 9 | [string]$authOptions, 10 | [string]$runOptions, 11 | [string]$appType, 12 | [string]$removeConflictingContainers, 13 | [string]$buildOnly, 14 | [string]$isWindowsContainer, 15 | [string]$isWebApp 16 | ) 17 | 18 | function Add-Override( 19 | $pubProps, 20 | [string]$name, 21 | [string]$value, 22 | [switch]$isBool 23 | ) { 24 | if ($value) { 25 | if ($isBool){ 26 | $value = Convert-String $value Boolean 27 | } 28 | $pubProps[$name] = $value 29 | } 30 | } 31 | 32 | Write-Verbose -Verbose "Starting Docker Publish step" 33 | 34 | # default location for publisingcp 35 | $pubProps = @{} 36 | Add-Override -pubProps $pubProps -name "DockerServerUrl" -value $serverUrl 37 | Add-Override -pubProps $pubProps -name "DockerImageName" -value $imageName 38 | Add-Override -pubProps $pubProps -name "DockerPublishHostPort" -value $hostPort 39 | Add-Override -pubProps $pubProps -name "DockerPublishContainerPort" -value $containerPort 40 | Add-Override -pubProps $pubProps -name "DockerAuthOptions" -value $authOptions 41 | Add-Override -pubProps $pubProps -name "DockerRunOptions" -value $runOptions 42 | Add-Override -pubProps $pubProps -name "DockerAppType" -value $appType 43 | Add-Override -pubProps $pubProps -name "DockerBuildOnly" -value $buildOnly -isBool 44 | Add-Override -pubProps $pubProps -name "DockerRemoveConflictingContainers" -value $removeConflictingContainers -isBool 45 | Add-Override -pubProps $pubProps -name "CreateWindowsContainer" -value $isWindowsContainer -isBool 46 | Add-Override -pubProps $pubProps -name "Dockerfile" -value (Split-Path -Leaf $pathToDockerfile) 47 | 48 | # never open a browser to the publsihed container 49 | Add-Override -pubProps $pubProps -name "LaunchSiteAfterPublish" -value "false" -isBool 50 | 51 | Write-Verbose -Verbose "Overriding pubxml values:" 52 | Write-Verbose -Verbose ($pubProps | Out-String) 53 | 54 | Write-Verbose -Verbose "Calling dockerPublishVS script" 55 | Write-Verbose -Verbose ".\dockerPublishVS.ps1 -publishProperties {pubProps} -packOutput $packOutput -pubxmlFile $pathToPubxml" 56 | & .\dockerPublishVS.ps1 -publishProperties $pubProps -packOutput $packOutput -pubxmlFile $pathToPubxml 57 | 58 | Write-Verbose -Verbose "Leaving Docker Publish step" -------------------------------------------------------------------------------- /Tasks/DockerPublish/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/Tasks/DockerPublish/icon.png -------------------------------------------------------------------------------- /Tasks/ReplaceTokens/.taskkey: -------------------------------------------------------------------------------- 1 | 06bb4d50-81b9-11e6-a200-d1d6dcd7093e -------------------------------------------------------------------------------- /Tasks/ReplaceTokens/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/Tasks/ReplaceTokens/icon.png -------------------------------------------------------------------------------- /Tasks/ReplaceTokens/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "colinsalmcornerbuildtasksreplacetokens", 3 | "version": "0.0.3", 4 | "description": "Replaces tokens in a file", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/colindembovsky/cols-agent-tasks" 11 | }, 12 | "keywords": [ 13 | "VSO", 14 | "build", 15 | "tasks" 16 | ], 17 | "author": "Colin Dembovsky (ColinsALMCorner.com)", 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/colindembovsky/cols-agent-tasks/issues" 21 | }, 22 | "homepage": "https://github.com/colindembovsky/cols-agent-tasks", 23 | "devDependencies": { 24 | "azure-pipelines-task-lib": "^4.17.3", 25 | "minimatch": "^3.0.5", 26 | "shelljs": "^0.8.5" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Tasks/RouteTraffic/README.md: -------------------------------------------------------------------------------- 1 | # Colin's ALM Corner Build Tasks - Site Experiment 2 | 3 | ![Tag Build/Release Task](../../images/ss_routeTraffic.png) 4 | 5 | ## Overview 6 | This task routes a specified percentage of traffic to an Azure Web App Slot. 7 | 8 | ## YAML 9 | ```yaml 10 | steps: 11 | - task: colinsalmcorner.colinsalmcorner-buildtasksbeta.route-traffic-task.azureWebAppRouteTraffic@0 12 | displayName: 'Route Traffic: 20% to staging on MySite' 13 | inputs: 14 | ConnectedServiceName: MyAzureEndpoint # Name of Azure ARM service endpoint 15 | WebAppName: MySite # Name of Azure Web App 16 | ResourceGroupName: 'My-RG' # Name of Web App resource group 17 | Slot: staging # slot to route % of traffic to (remainder goes to 'production' slot) 18 | percentTraffic: 20 # percentage of traffic to route to experimental slot 19 | ``` 20 | 21 | ## Settings 22 | The task requires the following settings: 23 | 24 | 1. **Azure subscription**: An Azure Resource Management subscription endpoint. 25 | 1. **App Service name**: The name of the App Service. 26 | 1. **Resource group**: The resource group that contains the App Service. 27 | 1. **Experiment slot**: The slot to direct a percentage of traffic to. 28 | 1. **Percentage to Route**: Tags to add to the build. Can be multi-line for multiple tags. 29 | 30 | ## Using this task for Hypothesis-driven Development 31 | You can see an example of how to use this task at this [blog post](http://bit.ly/routetraf). -------------------------------------------------------------------------------- /Tasks/RouteTraffic/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/Tasks/RouteTraffic/icon.png -------------------------------------------------------------------------------- /Tasks/RouteTraffic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "colinsalmcornerbuildtasksroutetraffic", 3 | "version": "0.0.3", 4 | "description": "Route Traffic for Web App", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/colindembovsky/cols-agent-tasks" 11 | }, 12 | "keywords": [ 13 | "VSO", 14 | "build", 15 | "tasks" 16 | ], 17 | "author": "Colin Dembovsky (ColinsALMCorner.com)", 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/colindembovsky/cols-agent-tasks/issues" 21 | }, 22 | "homepage": "https://github.com/colindembovsky/cols-agent-tasks", 23 | "devDependencies": { 24 | "azure-devops-node-api": "^14.1.0", 25 | "azure-pipelines-task-lib": "^4.17.3", 26 | "q": "^1.5.1", 27 | "xml2js": "^0.6.2" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Tasks/TagBuild/README.md: -------------------------------------------------------------------------------- 1 | # Colin's ALM Corner Build Tasks - Tag Build 2 | 3 | ![Tag Build/Release Task](../../images/ss_tagBuild.png) 4 | 5 | ## Overview 6 | This task tags a build/release with the tags specified. 7 | 8 | ## YAML 9 | 10 | ```yaml 11 | steps: 12 | - task: colinsalmcorner.colinsalmcorner-buildtasksbeta.tag-build-task.tagBuildOrRelease@0 13 | displayName: 'Tag Build' 14 | inputs: 15 | type: Build # Build or Release - specify which artifact to tag (default is Build) 16 | tags: | 17 | tag1 18 | tag2 19 | ``` 20 | 21 | ## Settings 22 | The task requires the following settings: 23 | 24 | 1. **Type**: Build or Release (see below for explanation). 25 | 1. **Tags**: Tags to add to the build. Can be multi-line for multiple tags. 26 | 27 | ## Permissions for Tagging Releases 28 | In order to tag releases, the build service identity needs `Manage Releases` permissions. If the permissions are not set the task will fail with this error: 29 | 30 | ``` 31 | VS402904: Access denied: User Project Collection Build Service does not have manage releases permission. Contact your release manager. 32 | ``` 33 | 34 | You can set the permission as follows: 35 | 1. Click on the ellipses on the `All release definitions` node in the Release explorer and click `Security`. 36 | ![All Releases security](../../images/releasePerm-security.png) 37 | 1. Click on the `Project Collection Build Service` and set `Manage Releases` to `Allow`. 38 | ![Set Manage Releases to Allow](../../images/releasePerm-set.png) 39 | 40 | ## Tagging Types Matrix 41 | 42 | | Definition Type | Tag Type | Notes | 43 | | --- | --- | ------ | 44 | | Build | Build | Tags the current build with the tags | 45 | | Build | Release | Throws an error | 46 | | Release | Release | Tags the current release with the tags | 47 | | Release | Build | Tags the primary build artifact's build with the tags | 48 | -------------------------------------------------------------------------------- /Tasks/TagBuild/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/Tasks/TagBuild/icon.png -------------------------------------------------------------------------------- /Tasks/TagBuild/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "colinsalmcornerbuildtaskstagbuild", 3 | "version": "0.0.3", 4 | "description": "Tag a Build", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/colindembovsky/cols-agent-tasks" 11 | }, 12 | "keywords": [ 13 | "VSO", 14 | "build", 15 | "tasks" 16 | ], 17 | "author": "Colin Dembovsky (ColinsALMCorner.com)", 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/colindembovsky/cols-agent-tasks/issues" 21 | }, 22 | "homepage": "https://github.com/colindembovsky/cols-agent-tasks", 23 | "devDependencies": { 24 | "azure-devops-node-api": "^14.1.0", 25 | "azure-pipelines-task-lib": "^4.17.3" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Tasks/TagBuild/task.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "5d741236-331c-4461-82a2-9d55eb91bb91", 3 | "name": "tagBuildOrRelease", 4 | "friendlyName": "Tag Build or Release", 5 | "description": "Adds tags to a build or release", 6 | "author": "Colin Dembovsky (colinsalmcorner.com)", 7 | "helpMarkDown": "[More Information](https://github.com/colindembovsky/cols-agent-tasks/tree/master/Tasks/TagBuild)", 8 | "category": "Utility", 9 | "visibility": [ 10 | "Build", 11 | "Release" 12 | ], 13 | "version": { 14 | "Major": "0", 15 | "Minor": "1", 16 | "Patch": "0" 17 | }, 18 | "minimumAgentVersion": "1.91.0", 19 | "instanceNameFormat": "Tag $(type)", 20 | "inputs": [ 21 | { 22 | "name": "type", 23 | "type": "pickList", 24 | "label": "Type", 25 | "defaultValue": "Build", 26 | "helpMarkDown": "Type of entity to tag. Set to build to let the build tag itself. Set to release to let the release tag itself. Set to build in a release to tag the _primary build_ for the release.", 27 | "required": true, 28 | "options": { 29 | "Build": "Build", 30 | "Release": "Release" 31 | } 32 | }, 33 | { 34 | "name": "tags", 35 | "type": "multiLine", 36 | "label": "Tags", 37 | "defaultValue": "", 38 | "helpMarkDown": "Tags to tag the build/release with. Use multiple lines to specify multiple tags.", 39 | "required": true 40 | } 41 | ], 42 | "execution": { 43 | "Node10": { 44 | "target": "tagBuild.js", 45 | "argumentFormat": "" 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Tasks/Tokenizer/.taskkey: -------------------------------------------------------------------------------- 1 | 06bb4d50-81b9-11e6-a200-d1d6dcd7093e -------------------------------------------------------------------------------- /Tasks/Tokenizer/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/Tasks/Tokenizer/icon.png -------------------------------------------------------------------------------- /Tasks/Tokenizer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "colinsalmcornerbuildtaskstokenizer", 3 | "version": "0.0.3", 4 | "description": "Tokenize a file", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/colindembovsky/cols-agent-tasks" 11 | }, 12 | "keywords": [ 13 | "VSO", 14 | "build", 15 | "tasks" 16 | ], 17 | "author": "Colin Dembovsky (ColinsALMCorner.com)", 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/colindembovsky/cols-agent-tasks/issues" 21 | }, 22 | "homepage": "https://github.com/colindembovsky/cols-agent-tasks", 23 | "devDependencies": { 24 | "azure-pipelines-task-lib": "^4.17.3", 25 | "minimatch": "^3.0.5", 26 | "shelljs": "^0.8.5" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Tasks/VersionAssemblies/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/Tasks/VersionAssemblies/icon.png -------------------------------------------------------------------------------- /Tasks/VersionAssemblies/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "colinsalmcornerbuildtasksversionassemblies", 3 | "version": "0.1.5", 4 | "description": "Versions assemblies", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/colindembovsky/cols-agent-tasks" 11 | }, 12 | "keywords": [ 13 | "VSO", 14 | "build", 15 | "tasks" 16 | ], 17 | "author": "Colin Dembovsky (ColinsALMCorner.com)", 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/colindembovsky/cols-agent-tasks/issues" 21 | }, 22 | "homepage": "https://github.com/colindembovsky/cols-agent-tasks", 23 | "devDependencies": { 24 | "azure-pipelines-task-lib": "^4.17.3", 25 | "minimatch": "^3.0.5", 26 | "shelljs": "^0.8.5" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Update-TaskIDs.ps1: -------------------------------------------------------------------------------- 1 | param ( 2 | [Switch]$Beta 3 | ) 4 | 5 | if ($Beta) { 6 | Write-Host -f Magenta "Switching to beta ids" 7 | } else { 8 | Write-Host -f Magenta "Switching to live ids" 9 | } 10 | 11 | $tasks = ConvertFrom-Json (gc .\taskIds.json -Raw) 12 | foreach ($task in $tasks.tasks) { 13 | Write-Host -f Yellow ("Converting task path {0}" -f $task.path) 14 | $path = Join-Path -Path "." -ChildPath $task.path 15 | $path = Join-Path -Path $path -ChildPath "task.json" 16 | $taskJson = ConvertFrom-Json (gc $path -Raw) 17 | if ($Beta) { 18 | $taskJson.id = $task.'beta-id' 19 | } else { 20 | $taskJson.id = $task.id 21 | } 22 | sc $path -Value (ConvertTo-Json $taskJson -Depth 100) 23 | } 24 | 25 | Write-Host "Done!" -f Green -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | name: 1.4$(Rev:.r) 2 | 3 | trigger: 4 | - main 5 | 6 | pr: 7 | - main 8 | 9 | stages: 10 | - stage: build 11 | displayName: Build and Test 12 | 13 | jobs: 14 | - template: templates/build-job.yml 15 | parameters: 16 | isBeta: ${{ eq(variables['Build.Reason'], 'PullRequest') }} 17 | 18 | - stage: publish 19 | displayName: Publish 20 | dependsOn: build 21 | jobs: 22 | - template: templates/deploy-job.yml 23 | ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/main') }}: 24 | parameters: 25 | env: marketplace 26 | envName: Marketplace -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | #FROM microsoft/dotnet:latest 2 | FROM colin/agentbase:latest 3 | 4 | # defaults - override them using --build-arg 5 | ARG AGENT_URL=https://github.com/Microsoft/vsts-agent/releases/download/v2.104.0/vsts-agent-ubuntu.14.04-x64-2.104.0.tar.gz 6 | ARG AGENT_NAME=docker 7 | ARG AGENT_POOL=default 8 | 9 | # you must supply these to the build command using --build-arg 10 | ARG VSTS_ACC 11 | ARG PAT 12 | 13 | # install git 14 | #RUN apt-get update && apt-get -y install software-properties-common && apt-add-repository ppa:git-core/ppa 15 | #RUN apt-get update && apt-get -y install git 16 | 17 | # prereqs required to run dotnet publish 18 | #RUN apt-get install -y nodejs-legacy npm 19 | #RUN npm install -g bower 20 | 21 | # create a user 22 | RUN useradd -ms /bin/bash agent 23 | USER agent 24 | WORKDIR /home/agent 25 | 26 | # download the agent tarball 27 | #RUN curl -Lo agent.tar.gz $AGENT_URL && tar xvf agent.tar.gz && rm agent.tar.gz 28 | COPY *.tar.gz . 29 | RUN tar xzf *.tar.gz && rm -f *.tar.gz 30 | RUN bin/Agent.Listener configure --url https://$VSTS_ACC.visualstudio.com --agent $AGENT_NAME --pool $AGENT_POOL --acceptteeeula --auth PAT --token $PAT --unattended 31 | 32 | ENTRYPOINT ./run.sh -------------------------------------------------------------------------------- /images/donate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/images/donate.png -------------------------------------------------------------------------------- /images/extension-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/images/extension-icon.png -------------------------------------------------------------------------------- /images/releasePerm-security.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/images/releasePerm-security.png -------------------------------------------------------------------------------- /images/releasePerm-set.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/images/releasePerm-set.png -------------------------------------------------------------------------------- /images/ss_AzureWebdeploy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/images/ss_AzureWebdeploy.png -------------------------------------------------------------------------------- /images/ss_DacPacChangeReport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/images/ss_DacPacChangeReport.png -------------------------------------------------------------------------------- /images/ss_coverageDelta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/images/ss_coverageDelta.png -------------------------------------------------------------------------------- /images/ss_coverageGate-options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/images/ss_coverageGate-options.png -------------------------------------------------------------------------------- /images/ss_coverageGate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/images/ss_coverageGate.png -------------------------------------------------------------------------------- /images/ss_dockerPublish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/images/ss_dockerPublish.png -------------------------------------------------------------------------------- /images/ss_replaceTokens.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/images/ss_replaceTokens.png -------------------------------------------------------------------------------- /images/ss_routeTraffic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/images/ss_routeTraffic.png -------------------------------------------------------------------------------- /images/ss_tagBuild.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/images/ss_tagBuild.png -------------------------------------------------------------------------------- /images/ss_tokenize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/images/ss_tokenize.png -------------------------------------------------------------------------------- /images/ss_versionAssemblies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindembovsky/cols-agent-tasks/e1ee8b1c487be999f98390651ef3546ed4afbc1c/images/ss_versionAssemblies.png -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Colin's ALM Corner Custom Build Tasks 2 | 3 | ![Build Status](https://colinsalmcorner.visualstudio.com/_apis/public/build/definitions/34532943-412e-4dac-b314-a87833e22dd8/22/badge) 4 | 5 | [![Donate](./images/donate.png)](https://www.paypal.me/ColinDembovsky/5) 6 | 7 | > As [Scott Hanselman](http://www.hanselman.com/) says, "donations pay for tacos" (or low carb equivalent). 8 | 9 | ## Overview 10 | This repo contains custom tasks that meant to be used with Visual Studio Online and Team Foundation Server. 11 | 12 | ## Build and Test 13 | Use `yarn` to build and test these extensions. All `yarn` scripts are specified in the `package.json` file. Run `yarn run` to get a prompt of all the targets. The most important are: 14 | 15 | 1. `install`: install dependencies in root folder. 16 | 1. `install-libs` install dependencies in each Task folder (required since each task has to be self-contained). 17 | 1. `test` to run tests. 18 | 1. `debugtest` to run tests with verbose logging. 19 | 1. `cover` to run tests with code coverage. 20 | 1. `prepextension` to run `install` and `coverage` (used to package the extension in the build). 21 | 22 | ## Tasks 23 | The following tasks are available: 24 | 25 | 1. **Version Assemblies** 26 | 27 | This task versions assemblies according to the build number. [More...](./Tasks/VersionAssemblies) 28 | 29 | 1. **Replace Tokens** 30 | 31 | This task replaces tokens in a file using Environment variables. [More...](./Tasks/ReplaceTokens) 32 | 33 | 1. **DacPac Change Report Task** 34 | 35 | This task calculates the changes in an SSDT project between builds. [More...](./Tasks/DacPacReport) 36 | 37 | 1. **Tokenizer** 38 | 39 | This task tokenizes a file automatically. [More...](./Tasks/Tokenizer) 40 | 41 | 1. **Coverage Gate** 42 | 43 | This task allows you to fail a release (or build) based of coverage delta. [More...](./Tasks/CoverageGate) 44 | 45 | ## Changing the Code 46 | The easiest way to open the source is to clone the repo and open in [VSCode](https://code.visualstudio.com/). 47 | If you change the .ts files, then run build (ctrl-shift-b) to compile the .js files. 48 | 49 | ## Creating the Extension Package 50 | Help Pages can be found [here](https://www.visualstudio.com/en-us/integrate/extensions/overview). 51 | 52 | To compile the extension, update the version number in the `extension-manifest.json` file and run: 53 | ``` 54 | tfx extension create --manifest-globs .\vss-extension.json 55 | ``` 56 | 57 | Upload to the marketplace by singing in to your [publisher profile](http://aka.ms/vsmarketplace-manage). 58 | -------------------------------------------------------------------------------- /taskIds.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": [ 3 | { 4 | "path": "Tasks/AzureWebDeploy", 5 | "id": "5C9EA8BE-E6FB-4AE7-905E-67BFD6741967", 6 | "beta-id": "95c56258-9a45-4afe-b862-f1c74efceabe" 7 | }, 8 | { 9 | "path": "Tasks/CoverageGate", 10 | "id": "0b6f0167-8389-4db8-89c6-4ae7688cd15a", 11 | "beta-id": "6712132c-98a9-42e0-a375-fcbe414e5269" 12 | }, 13 | { 14 | "path": "Tasks/DacPacReport", 15 | "id": "1EBF2967-63B3-4372-89F7-6799108A22F0", 16 | "beta-id": "5030ea81-41b7-4163-805b-f8e0116e8da3" 17 | }, 18 | { 19 | "path": "Tasks/DockerPublish", 20 | "id": "639B8E0C-2C2C-41E7-B822-4D03AEFCB92B", 21 | "beta-id": "f7c44198-1c25-477f-a9d2-01e36d3244a5" 22 | }, 23 | { 24 | "path": "Tasks/ReplaceTokens", 25 | "id": "9240B5C1-A1B2-4799-9325-E071C63236FB", 26 | "beta-id": "1d7dea50-482b-4b76-85d7-d4bf151d00b5" 27 | }, 28 | { 29 | "path": "Tasks/Tokenizer", 30 | "id": "6D9895EB-8056-4111-B4B3-7B80FD383E44", 31 | "beta-id": "d865ae36-7794-4a1f-a6bd-6d10043438db" 32 | }, 33 | { 34 | "path": "Tasks/VersionAssemblies", 35 | "id": "5b4d14d0-3868-11e4-a31d-3f0a2d8202f4", 36 | "beta-id": "ab6ca715-6f11-4f14-a578-12ca85409ea6" 37 | }, 38 | { 39 | "path": "Tasks/TagBuild", 40 | "id": "5d741236-331c-4461-82a2-9d55eb91bb91", 41 | "beta-id": "655a1b4d-2572-45f4-9e0a-4acfb6be8daf" 42 | }, 43 | { 44 | "path": "Tasks/RouteTraffic", 45 | "id": "aafd0d72-ff21-4439-b282-44be5e9d4d90", 46 | "beta-id": "fb05e250-c1fd-4428-b1fb-2813686bc1b8" 47 | } 48 | ] 49 | } -------------------------------------------------------------------------------- /templates/deploy-job.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | env: cacdemo 3 | envName: Beta 4 | 5 | jobs: 6 | - deployment: ${{ parameters.env }} 7 | displayName: ${{ parameters.envName }} 8 | pool: 9 | vmImage: ubuntu-latest 10 | environment: ${{ parameters.env }} 11 | variables: 12 | ${{ if eq(parameters.envName, 'Beta') }}: 13 | fileName: colinsalmcorner.colinsalmcorner-buildtasks-beta-$(Build.BuildNumber).vsix 14 | ${{ if ne(parameters.envName, 'Beta') }}: 15 | fileName: colinsalmcorner.colinsalmcorner-buildtasks-$(Build.BuildNumber).vsix 16 | strategy: 17 | runOnce: 18 | deploy: 19 | steps: 20 | - download: none 21 | - task: DownloadBuildArtifacts@0 22 | displayName: Download vsix 23 | inputs: 24 | artifactName: vsix 25 | pattern: ${{ parameters.vsixPattern }} 26 | - task: TfxInstaller@3 27 | displayName: 'Use Node CLI for Azure DevOps' 28 | inputs: 29 | version: '0.17.x' 30 | checkLatest: true 31 | - task: PublishAzureDevOpsExtension@3 32 | displayName: Publish Extension 33 | inputs: 34 | connectedServiceName: MarketPlace 35 | fileType: vsix 36 | vsixFile: '$(Build.ArtifactStagingDirectory)/vsix/$(fileName)' 37 | updateTasksVersion: false 38 | noWaitValidation: true 39 | #shareWith: cacdemo 40 | 41 | - ${{ if eq(parameters.envName, 'Beta') }}: 42 | - script: echo "Test workflows in https://dev.azure.com/cacdemo/Demo/" 43 | displayName: Reminder of testing URL 44 | 45 | - ${{ if ne(parameters.envName, 'Beta') }}: 46 | - task: colinsalmcorner.colinsalmcorner-buildtasks.tag-build-task.tagBuildOrRelease@0 47 | displayName: Tag Build 48 | inputs: 49 | tags: | 50 | releasedToPublic 51 | $(Build.BuildNumber) -------------------------------------------------------------------------------- /test/coverageGate/mocks.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.MockWebApi = void 0; 4 | var MockWebApi; 5 | (function (MockWebApi) { 6 | MockWebApi.calledBasic = false; 7 | MockWebApi.calledBearer = false; 8 | var mockCredHandler = { 9 | prepareRequest: (options) => { }, 10 | canHandleAuthentication: (res) => true, 11 | handleAuthentication: (httpClient, protocol, options, objs, finalCallback) => { } 12 | }; 13 | function getBasicHandler(username, password) { 14 | console.log("--- MOCK: return fake basic handler"); 15 | MockWebApi.calledBasic = true; 16 | return mockCredHandler; 17 | } 18 | MockWebApi.getBasicHandler = getBasicHandler; 19 | function getBearerHandler(token) { 20 | console.log("--- MOCK: return fake bearer handler"); 21 | MockWebApi.calledBearer = true; 22 | return mockCredHandler; 23 | } 24 | MockWebApi.getBearerHandler = getBearerHandler; 25 | class WebApi { 26 | constructor(tpcUri, credHandler) { 27 | } 28 | getTestApi() { 29 | return { 30 | getCodeCoverageSummary: (teamProject, buildId) => MockWebApi.covData 31 | }; 32 | } 33 | } 34 | MockWebApi.WebApi = WebApi; 35 | })(MockWebApi = exports.MockWebApi || (exports.MockWebApi = {})); 36 | //# sourceMappingURL=mocks.js.map -------------------------------------------------------------------------------- /test/coverageGate/mocks.ts: -------------------------------------------------------------------------------- 1 | export module MockWebApi { 2 | export var covData; 3 | export var calledBasic = false; 4 | export var calledBearer = false; 5 | 6 | var mockCredHandler = { // a mock IRequestHandler 7 | prepareRequest: (options: any) => { }, 8 | canHandleAuthentication: (res) => true, 9 | handleAuthentication: (httpClient: any, protocol: any, options: any, objs: any, finalCallback: any) => { } 10 | }; 11 | 12 | export function getBasicHandler(username, password) { 13 | console.log("--- MOCK: return fake basic handler"); 14 | calledBasic = true; 15 | return mockCredHandler; 16 | } 17 | 18 | export function getBearerHandler(token) { 19 | console.log("--- MOCK: return fake bearer handler"); 20 | calledBearer = true; 21 | return mockCredHandler; 22 | } 23 | 24 | export class WebApi { 25 | constructor(tpcUri, credHandler) { 26 | } 27 | 28 | getTestApi() { 29 | return { 30 | getCodeCoverageSummary: (teamProject, buildId) => covData 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /test/coverageGate/test-lessEqual0-fails.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const mocks = require("./mocks"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'CoverageGate'); 7 | let taskPath = path.join(rootDir, 'coverageGate.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // provide mocks 10 | mocks.MockWebApi.covData = { 11 | coverageData: [{ 12 | coverageStats: [ 13 | { 14 | isDeltaAvailable: true, 15 | label: 'Lines', 16 | delta: 0 17 | }, 18 | { 19 | isDeltaAvailable: true, 20 | label: 'Blocks', 21 | delta: 0 22 | } 23 | ] 24 | } 25 | ] 26 | }; 27 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 28 | // set variables 29 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 30 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 31 | process.env["BUILD_BUILDID"] = "1"; 32 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 33 | // set inputs 34 | tmr.setInput('minDelta', "0"); 35 | tmr.setInput('operator', "le"); 36 | tmr.run(); 37 | //# sourceMappingURL=test-lessEqual0-fails.js.map -------------------------------------------------------------------------------- /test/coverageGate/test-lessEqual0-fails.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import assert = require('assert'); 5 | import mocks = require('./mocks'); 6 | 7 | let rootDir = path.join(__dirname, '../../Tasks', 'CoverageGate'); 8 | let taskPath = path.join(rootDir, 'coverageGate.js'); 9 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 10 | 11 | // provide mocks 12 | mocks.MockWebApi.covData = { 13 | coverageData: [{ 14 | coverageStats: [ 15 | { 16 | isDeltaAvailable: true, 17 | label: 'Lines', 18 | delta: 0 19 | }, 20 | { 21 | isDeltaAvailable: true, 22 | label: 'Blocks', 23 | delta: 0 24 | } 25 | ] 26 | } 27 | ] 28 | }; 29 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 30 | 31 | // set variables 32 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 33 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 34 | process.env["BUILD_BUILDID"] = "1"; 35 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 36 | 37 | // set inputs 38 | tmr.setInput('minDelta', "0"); 39 | tmr.setInput('operator', "le"); 40 | 41 | tmr.run(); -------------------------------------------------------------------------------- /test/coverageGate/test-lessThan0-succeeds.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const mocks = require("./mocks"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'CoverageGate'); 7 | let taskPath = path.join(rootDir, 'coverageGate.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // provide mocks 10 | mocks.MockWebApi.covData = { 11 | coverageData: [{ 12 | coverageStats: [ 13 | { 14 | isDeltaAvailable: true, 15 | label: 'Lines', 16 | delta: 0 17 | }, 18 | { 19 | isDeltaAvailable: true, 20 | label: 'Blocks', 21 | delta: 0 22 | } 23 | ] 24 | } 25 | ] 26 | }; 27 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 28 | // set variables 29 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 30 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 31 | process.env["BUILD_BUILDID"] = "1"; 32 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 33 | // set inputs 34 | tmr.setInput('minDelta', "0"); 35 | tmr.setInput('operator', "lt"); 36 | tmr.run(); 37 | // assert to check bearer auth 38 | if (mocks.MockWebApi.calledBearer) { 39 | console.log("Bearer auth called."); 40 | } 41 | else { 42 | console.error("Bearer auth not called."); 43 | } 44 | if (mocks.MockWebApi.calledBasic) { 45 | console.error("Basic auth called."); 46 | } 47 | else { 48 | console.log("Basic auth not called."); 49 | } 50 | //# sourceMappingURL=test-lessThan0-succeeds.js.map -------------------------------------------------------------------------------- /test/coverageGate/test-lessThan0-succeeds.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import assert = require('assert'); 5 | import mocks = require('./mocks'); 6 | 7 | let rootDir = path.join(__dirname, '../../Tasks', 'CoverageGate'); 8 | let taskPath = path.join(rootDir, 'coverageGate.js'); 9 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 10 | 11 | // provide mocks 12 | mocks.MockWebApi.covData = { 13 | coverageData: [{ 14 | coverageStats: [ 15 | { 16 | isDeltaAvailable: true, 17 | label: 'Lines', 18 | delta: 0 19 | }, 20 | { 21 | isDeltaAvailable: true, 22 | label: 'Blocks', 23 | delta: 0 24 | } 25 | ] 26 | } 27 | ] 28 | }; 29 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 30 | 31 | // set variables 32 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 33 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 34 | process.env["BUILD_BUILDID"] = "1"; 35 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 36 | 37 | // set inputs 38 | tmr.setInput('minDelta', "0"); 39 | tmr.setInput('operator', "lt"); 40 | 41 | tmr.run(); 42 | 43 | // assert to check bearer auth 44 | if (mocks.MockWebApi.calledBearer) { 45 | console.log("Bearer auth called."); 46 | } else { 47 | console.error("Bearer auth not called.") 48 | } 49 | 50 | if (mocks.MockWebApi.calledBasic) { 51 | console.error("Basic auth called."); 52 | } else { 53 | console.log("Basic auth not called.") 54 | } -------------------------------------------------------------------------------- /test/coverageGate/test-negdelta-succeeds.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const mocks = require("./mocks"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'CoverageGate'); 7 | let taskPath = path.join(rootDir, 'coverageGate.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // provide mocks 10 | mocks.MockWebApi.covData = { 11 | coverageData: [{ 12 | coverageStats: [ 13 | { 14 | isDeltaAvailable: true, 15 | label: 'Lines', 16 | delta: -1 17 | }, 18 | { 19 | isDeltaAvailable: true, 20 | label: 'Blocks', 21 | delta: 3 22 | } 23 | ] 24 | } 25 | ] 26 | }; 27 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 28 | // set variables 29 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 30 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 31 | process.env["BUILD_BUILDID"] = "1"; 32 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 33 | // set inputs 34 | tmr.setInput('minDelta', "-2"); 35 | tmr.setInput('operator', "lt"); 36 | tmr.run(); 37 | //# sourceMappingURL=test-negdelta-succeeds.js.map -------------------------------------------------------------------------------- /test/coverageGate/test-negdelta-succeeds.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import assert = require('assert'); 5 | import mocks = require('./mocks'); 6 | 7 | let rootDir = path.join(__dirname, '../../Tasks', 'CoverageGate'); 8 | let taskPath = path.join(rootDir, 'coverageGate.js'); 9 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 10 | 11 | // provide mocks 12 | mocks.MockWebApi.covData = { 13 | coverageData: [{ 14 | coverageStats: [ 15 | { 16 | isDeltaAvailable: true, 17 | label: 'Lines', 18 | delta: -1 19 | }, 20 | { 21 | isDeltaAvailable: true, 22 | label: 'Blocks', 23 | delta: 3 24 | } 25 | ] 26 | } 27 | ] 28 | }; 29 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 30 | 31 | // set variables 32 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 33 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 34 | process.env["BUILD_BUILDID"] = "1"; 35 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 36 | 37 | // set inputs 38 | tmr.setInput('minDelta', "-2"); 39 | tmr.setInput('operator', "lt"); 40 | 41 | tmr.run(); -------------------------------------------------------------------------------- /test/coverageGate/test-noauth-fails.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const mocks = require("./mocks"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'CoverageGate'); 7 | let taskPath = path.join(rootDir, 'coverageGate.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // provide mocks 10 | mocks.MockWebApi.covData = { 11 | coverageData: [{ 12 | coverageStats: [ 13 | { 14 | isDeltaAvailable: true, 15 | label: 'Lines', 16 | delta: 0 17 | }, 18 | { 19 | isDeltaAvailable: true, 20 | label: 'Blocks', 21 | delta: 0 22 | } 23 | ] 24 | } 25 | ] 26 | }; 27 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 28 | // set variables 29 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 30 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 31 | process.env["BUILD_BUILDID"] = "1"; 32 | // set inputs 33 | tmr.setInput('minDelta', "0"); 34 | tmr.setInput('operator', "le"); 35 | tmr.run(); 36 | //# sourceMappingURL=test-noauth-fails.js.map -------------------------------------------------------------------------------- /test/coverageGate/test-noauth-fails.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import assert = require('assert'); 5 | import mocks = require('./mocks'); 6 | 7 | let rootDir = path.join(__dirname, '../../Tasks', 'CoverageGate'); 8 | let taskPath = path.join(rootDir, 'coverageGate.js'); 9 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 10 | 11 | // provide mocks 12 | mocks.MockWebApi.covData = { 13 | coverageData: [{ 14 | coverageStats: [ 15 | { 16 | isDeltaAvailable: true, 17 | label: 'Lines', 18 | delta: 0 19 | }, 20 | { 21 | isDeltaAvailable: true, 22 | label: 'Blocks', 23 | delta: 0 24 | } 25 | ] 26 | } 27 | ] 28 | }; 29 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 30 | 31 | // set variables 32 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 33 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 34 | process.env["BUILD_BUILDID"] = "1"; 35 | 36 | // set inputs 37 | tmr.setInput('minDelta', "0"); 38 | tmr.setInput('operator', "le"); 39 | 40 | tmr.run(); -------------------------------------------------------------------------------- /test/coverageGate/test-nodata-fails.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const mocks = require("./mocks"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'CoverageGate'); 7 | let taskPath = path.join(rootDir, 'coverageGate.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // provide mocks 10 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 11 | // set variables 12 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 13 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 14 | process.env["BUILD_BUILDID"] = "1"; 15 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 16 | // set inputs 17 | tmr.setInput('minDelta', "0"); 18 | tmr.setInput('operator', "le"); 19 | tmr.run(); 20 | //# sourceMappingURL=test-nodata-fails.js.map -------------------------------------------------------------------------------- /test/coverageGate/test-nodata-fails.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import assert = require('assert'); 5 | import mocks = require('./mocks'); 6 | 7 | let rootDir = path.join(__dirname, '../../Tasks', 'CoverageGate'); 8 | let taskPath = path.join(rootDir, 'coverageGate.js'); 9 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 10 | 11 | // provide mocks 12 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 13 | 14 | // set variables 15 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 16 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 17 | process.env["BUILD_BUILDID"] = "1"; 18 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 19 | 20 | // set inputs 21 | tmr.setInput('minDelta', "0"); 22 | tmr.setInput('operator', "le"); 23 | 24 | tmr.run(); -------------------------------------------------------------------------------- /test/coverageGate/test-nodelta-fails.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const mocks = require("./mocks"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'CoverageGate'); 7 | let taskPath = path.join(rootDir, 'coverageGate.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // provide mocks 10 | mocks.MockWebApi.covData = { 11 | coverageData: [{ 12 | coverageStats: [ 13 | { 14 | isDeltaAvailable: false, 15 | label: 'Lines', 16 | delta: 0 17 | }, 18 | { 19 | isDeltaAvailable: false, 20 | label: 'Blocks', 21 | delta: 0 22 | } 23 | ] 24 | } 25 | ] 26 | }; 27 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 28 | // set variables 29 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 30 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 31 | process.env["BUILD_BUILDID"] = "1"; 32 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 33 | // set inputs 34 | tmr.setInput('minDelta', "0"); 35 | tmr.setInput('operator', "le"); 36 | tmr.run(); 37 | //# sourceMappingURL=test-nodelta-fails.js.map -------------------------------------------------------------------------------- /test/coverageGate/test-nodelta-fails.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import assert = require('assert'); 5 | import mocks = require('./mocks'); 6 | 7 | let rootDir = path.join(__dirname, '../../Tasks', 'CoverageGate'); 8 | let taskPath = path.join(rootDir, 'coverageGate.js'); 9 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 10 | 11 | // provide mocks 12 | mocks.MockWebApi.covData = { 13 | coverageData: [{ 14 | coverageStats: [ 15 | { 16 | isDeltaAvailable: false, 17 | label: 'Lines', 18 | delta: 0 19 | }, 20 | { 21 | isDeltaAvailable: false, 22 | label: 'Blocks', 23 | delta: 0 24 | } 25 | ] 26 | } 27 | ] 28 | }; 29 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 30 | 31 | // set variables 32 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 33 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 34 | process.env["BUILD_BUILDID"] = "1"; 35 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 36 | 37 | // set inputs 38 | tmr.setInput('minDelta', "0"); 39 | tmr.setInput('operator', "le"); 40 | 41 | tmr.run(); -------------------------------------------------------------------------------- /test/coverageGate/test-posdelta-succeeds.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const mocks = require("./mocks"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'CoverageGate'); 7 | let taskPath = path.join(rootDir, 'coverageGate.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // provide mocks 10 | mocks.MockWebApi.covData = { 11 | coverageData: [{ 12 | coverageStats: [ 13 | { 14 | isDeltaAvailable: true, 15 | label: 'Lines', 16 | delta: 2 17 | }, 18 | { 19 | isDeltaAvailable: true, 20 | label: 'Blocks', 21 | delta: 1 22 | } 23 | ] 24 | } 25 | ] 26 | }; 27 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 28 | // set variables 29 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 30 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 31 | process.env["BUILD_BUILDID"] = "1"; 32 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 33 | // set inputs 34 | tmr.setInput('minDelta', "1.5"); 35 | tmr.setInput('operator', "lt"); 36 | tmr.run(); 37 | //# sourceMappingURL=test-posdelta-succeeds.js.map -------------------------------------------------------------------------------- /test/coverageGate/test-posdelta-succeeds.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import assert = require('assert'); 5 | import mocks = require('./mocks'); 6 | 7 | let rootDir = path.join(__dirname, '../../Tasks', 'CoverageGate'); 8 | let taskPath = path.join(rootDir, 'coverageGate.js'); 9 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 10 | 11 | // provide mocks 12 | mocks.MockWebApi.covData = { 13 | coverageData: [{ 14 | coverageStats: [ 15 | { 16 | isDeltaAvailable: true, 17 | label: 'Lines', 18 | delta: 2 19 | }, 20 | { 21 | isDeltaAvailable: true, 22 | label: 'Blocks', 23 | delta: 1 24 | } 25 | ] 26 | } 27 | ] 28 | }; 29 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 30 | 31 | // set variables 32 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 33 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 34 | process.env["BUILD_BUILDID"] = "1"; 35 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 36 | 37 | // set inputs 38 | tmr.setInput('minDelta', "1.5"); 39 | tmr.setInput('operator', "lt"); 40 | 41 | tmr.run(); -------------------------------------------------------------------------------- /test/coverageGate/test-username-succeeds.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const mocks = require("./mocks"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'CoverageGate'); 7 | let taskPath = path.join(rootDir, 'coverageGate.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // provide mocks 10 | mocks.MockWebApi.covData = { 11 | coverageData: [{ 12 | coverageStats: [ 13 | { 14 | isDeltaAvailable: true, 15 | label: 'Lines', 16 | delta: 0 17 | }, 18 | { 19 | isDeltaAvailable: true, 20 | label: 'Blocks', 21 | delta: 0 22 | } 23 | ] 24 | } 25 | ] 26 | }; 27 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 28 | // set variables 29 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 30 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 31 | process.env["BUILD_BUILDID"] = "1"; 32 | // set inputs 33 | tmr.setInput('minDelta', "0"); 34 | tmr.setInput('operator', "lt"); 35 | tmr.setInput('username', "bob"); 36 | tmr.setInput('password', "p@ssw0rd"); 37 | tmr.run(); 38 | // assert 39 | if (mocks.MockWebApi.calledBearer) { 40 | console.error("Bearer auth called."); 41 | } 42 | else { 43 | console.log("Bearer auth not called."); 44 | } 45 | if (mocks.MockWebApi.calledBasic) { 46 | console.log("Basic auth called."); 47 | } 48 | else { 49 | console.error("Basic auth not called."); 50 | } 51 | //# sourceMappingURL=test-username-succeeds.js.map -------------------------------------------------------------------------------- /test/coverageGate/test-username-succeeds.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import assert = require('assert'); 5 | import mocks = require('./mocks'); 6 | 7 | let rootDir = path.join(__dirname, '../../Tasks', 'CoverageGate'); 8 | let taskPath = path.join(rootDir, 'coverageGate.js'); 9 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 10 | 11 | // provide mocks 12 | mocks.MockWebApi.covData = { 13 | coverageData: [{ 14 | coverageStats: [ 15 | { 16 | isDeltaAvailable: true, 17 | label: 'Lines', 18 | delta: 0 19 | }, 20 | { 21 | isDeltaAvailable: true, 22 | label: 'Blocks', 23 | delta: 0 24 | } 25 | ] 26 | } 27 | ] 28 | }; 29 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 30 | 31 | // set variables 32 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 33 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 34 | process.env["BUILD_BUILDID"] = "1"; 35 | 36 | // set inputs 37 | tmr.setInput('minDelta', "0"); 38 | tmr.setInput('operator', "lt"); 39 | tmr.setInput('username', "bob"); 40 | tmr.setInput('password', "p@ssw0rd"); 41 | 42 | tmr.run(); 43 | 44 | // assert 45 | if (mocks.MockWebApi.calledBearer) { 46 | console.error("Bearer auth called."); 47 | } else { 48 | console.log("Bearer auth not called.") 49 | } 50 | 51 | if (mocks.MockWebApi.calledBasic) { 52 | console.log("Basic auth called."); 53 | } else { 54 | console.error("Basic auth not called.") 55 | } -------------------------------------------------------------------------------- /test/replaceTokens/test-arrays.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const fs = require("fs"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'ReplaceTokens'); 7 | let taskPath = path.join(rootDir, 'replaceTokens.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // set up a tmp file for the test 10 | var workingFolder = path.join(__dirname, "working"); 11 | if (!fs.existsSync(workingFolder)) { 12 | fs.mkdirSync(workingFolder); 13 | } 14 | var tmpFile = path.join(workingFolder, "file.json"); 15 | // provide answers for task mock 16 | let a = { 17 | "checkPath": { 18 | "working": true 19 | }, 20 | "findMatch": { 21 | "*.json": [tmpFile] 22 | } 23 | }; 24 | tmr.setAnswers(a); 25 | fs.writeFile(tmpFile, ` 26 | { 27 | "Auth": { 28 | "ClientSecret": "Secret", 29 | "ValidAudiences": [ 30 | "__Auth.ValidAudiences[]__" 31 | ], 32 | "ConnectionStringKVSecretName": "__Auth.CS__" 33 | } 34 | } 35 | `, (err) => { 36 | // set inputs 37 | tmr.setInput('sourcePath', "working"); 38 | tmr.setInput('filePattern', '*.json'); 39 | tmr.setInput('tokenRegex', '__(\\w+[\\.\\w+]+(\\[\\])?)__'); 40 | // set variables 41 | process.env["AUTH_VALIDAUDIENCES"] = "a,b,c"; 42 | process.env["AUTH_CS"] = "someval"; 43 | tmr.run(); 44 | // validate the replacement 45 | let actual = fs.readFileSync(tmpFile).toString(); 46 | var expected = ` 47 | { 48 | "Auth": { 49 | "ClientSecret": "Secret", 50 | "ValidAudiences": [ 51 | "a","b","c" 52 | ], 53 | "ConnectionStringKVSecretName": "someval" 54 | } 55 | } 56 | `; 57 | if (actual.trim() !== expected.trim()) { 58 | console.log(actual); 59 | console.error("Replacement failed."); 60 | } 61 | else { 62 | console.log("Replacement succeeded!"); 63 | } 64 | }); 65 | //# sourceMappingURL=test-arrays.js.map -------------------------------------------------------------------------------- /test/replaceTokens/test-arrays.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import fs = require('fs'); 5 | 6 | let rootDir = path.join(__dirname, '../../Tasks', 'ReplaceTokens'); 7 | let taskPath = path.join(rootDir, 'replaceTokens.js'); 8 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 9 | 10 | // set up a tmp file for the test 11 | var workingFolder = path.join(__dirname, "working"); 12 | if (!fs.existsSync(workingFolder)) { 13 | fs.mkdirSync(workingFolder); 14 | } 15 | var tmpFile = path.join(workingFolder, "file.json"); 16 | 17 | // provide answers for task mock 18 | let a: ma.TaskLibAnswers = { 19 | "checkPath": { 20 | "working": true 21 | }, 22 | "findMatch": { 23 | "*.json" : [ tmpFile ] 24 | } 25 | }; 26 | tmr.setAnswers(a); 27 | 28 | fs.writeFile(tmpFile, ` 29 | { 30 | "Auth": { 31 | "ClientSecret": "Secret", 32 | "ValidAudiences": [ 33 | "__Auth.ValidAudiences[]__" 34 | ], 35 | "ConnectionStringKVSecretName": "__Auth.CS__" 36 | } 37 | } 38 | `, 39 | (err) => { 40 | 41 | // set inputs 42 | tmr.setInput('sourcePath', "working"); 43 | tmr.setInput('filePattern', '*.json'); 44 | tmr.setInput('tokenRegex', '__(\\w+[\\.\\w+]+(\\[\\])?)__'); 45 | 46 | // set variables 47 | process.env["AUTH_VALIDAUDIENCES"] = "a,b,c"; 48 | process.env["AUTH_CS"] = "someval"; 49 | 50 | tmr.run(); 51 | 52 | // validate the replacement 53 | let actual = fs.readFileSync(tmpFile).toString(); 54 | var expected = ` 55 | { 56 | "Auth": { 57 | "ClientSecret": "Secret", 58 | "ValidAudiences": [ 59 | "a","b","c" 60 | ], 61 | "ConnectionStringKVSecretName": "someval" 62 | } 63 | } 64 | `; 65 | 66 | if (actual.trim() !== expected.trim()) { 67 | console.log(actual); 68 | console.error("Replacement failed."); 69 | } else { 70 | console.log("Replacement succeeded!") 71 | } 72 | }); 73 | -------------------------------------------------------------------------------- /test/replaceTokens/test-ascii.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const fs = require("fs"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'ReplaceTokens'); 7 | let taskPath = path.join(rootDir, 'replaceTokens.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // set up a tmp file for the test 10 | var workingFolder = path.join(__dirname, "working"); 11 | if (!fs.existsSync(workingFolder)) { 12 | fs.mkdirSync(workingFolder); 13 | } 14 | var tmpFile = path.join(workingFolder, "file.config"); 15 | // provide answers for task mock 16 | let a = { 17 | "checkPath": { 18 | "working": true 19 | }, 20 | "findMatch": { 21 | "*.config": [tmpFile] 22 | } 23 | }; 24 | tmr.setAnswers(a); 25 | fs.writeFile(tmpFile, ` 26 | 27 | 28 | 29 | 30 | 31 | 32 | `, (err) => { 33 | // set inputs 34 | tmr.setInput('sourcePath', "working"); 35 | tmr.setInput('filePattern', '*.config'); 36 | tmr.setInput('tokenRegex', '__(\\w+)__'); 37 | // set variables 38 | process.env["COOLKEY"] = "MyCoolKey"; 39 | process.env["SECRET_Secret1"] = "supersecret1"; 40 | tmr.run(); 41 | // validate the replacement 42 | let actual = fs.readFileSync(tmpFile).toString(); 43 | var expected = ` 44 | 45 | 46 | 47 | 48 | 49 | 50 | `; 51 | if (actual.trim() !== expected.trim()) { 52 | console.log(actual); 53 | console.error("Replacement failed."); 54 | } 55 | else { 56 | console.log("Replacement succeeded!"); 57 | } 58 | }); 59 | //# sourceMappingURL=test-ascii.js.map -------------------------------------------------------------------------------- /test/replaceTokens/test-ascii.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import fs = require('fs'); 5 | 6 | let rootDir = path.join(__dirname, '../../Tasks', 'ReplaceTokens'); 7 | let taskPath = path.join(rootDir, 'replaceTokens.js'); 8 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 9 | 10 | // set up a tmp file for the test 11 | var workingFolder = path.join(__dirname, "working"); 12 | if (!fs.existsSync(workingFolder)) { 13 | fs.mkdirSync(workingFolder); 14 | } 15 | var tmpFile = path.join(workingFolder, "file.config"); 16 | 17 | // provide answers for task mock 18 | let a: ma.TaskLibAnswers = { 19 | "checkPath": { 20 | "working": true 21 | }, 22 | "findMatch": { 23 | "*.config" : [ tmpFile ] 24 | } 25 | }; 26 | tmr.setAnswers(a); 27 | 28 | fs.writeFile(tmpFile, ` 29 | 30 | 31 | 32 | 33 | 34 | 35 | `, 36 | (err) => { 37 | 38 | // set inputs 39 | tmr.setInput('sourcePath', "working"); 40 | tmr.setInput('filePattern', '*.config'); 41 | tmr.setInput('tokenRegex', '__(\\w+)__'); 42 | 43 | // set variables 44 | process.env["COOLKEY"] = "MyCoolKey"; 45 | process.env["SECRET_Secret1"] = "supersecret1"; 46 | 47 | tmr.run(); 48 | 49 | // validate the replacement 50 | let actual = fs.readFileSync(tmpFile).toString(); 51 | var expected = ` 52 | 53 | 54 | 55 | 56 | 57 | 58 | `; 59 | 60 | if (actual.trim() !== expected.trim()) { 61 | console.log(actual); 62 | console.error("Replacement failed."); 63 | } else { 64 | console.log("Replacement succeeded!") 65 | } 66 | }); 67 | -------------------------------------------------------------------------------- /test/replaceTokens/test-atTokens.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const fs = require("fs"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'ReplaceTokens'); 7 | let taskPath = path.join(rootDir, 'replaceTokens.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // set up a tmp file for the test 10 | var workingFolder = path.join(__dirname, "working"); 11 | if (!fs.existsSync(workingFolder)) { 12 | fs.mkdirSync(workingFolder); 13 | } 14 | var tmpFile = path.join(workingFolder, "appsettings.config"); 15 | // provide answers for task mock 16 | let a = { 17 | "checkPath": { 18 | "working": true 19 | }, 20 | "findMatch": { 21 | "*.config": [tmpFile] 22 | } 23 | }; 24 | tmr.setAnswers(a); 25 | fs.writeFile(tmpFile, ` 26 | 27 | 28 | 29 | 30 | 31 | `, (err) => { 32 | // set inputs 33 | tmr.setInput('sourcePath', "working"); 34 | tmr.setInput('filePattern', '*.config'); 35 | tmr.setInput('tokenRegex', '@@(\\w+)@@'); 36 | // set variables 37 | process.env["CUSTOM_BUILDMAJORNUM"] = "1"; 38 | process.env["CUSTOM_BUILDMINORNUM"] = "2"; 39 | process.env["CUSTOM_BUILDPATCHNUM"] = "3"; 40 | tmr.run(); 41 | // validate the replacement 42 | let actual = fs.readFileSync(tmpFile).toString(); 43 | var expected = ` 44 | 45 | 46 | 47 | 48 | 49 | `; 50 | if (actual.trim() !== expected.trim()) { 51 | console.log(actual); 52 | console.error("Replacement failed."); 53 | } 54 | else { 55 | console.log("Replacement succeeded!"); 56 | } 57 | }); 58 | //# sourceMappingURL=test-atTokens.js.map -------------------------------------------------------------------------------- /test/replaceTokens/test-atTokens.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import fs = require('fs'); 5 | 6 | let rootDir = path.join(__dirname, '../../Tasks', 'ReplaceTokens'); 7 | let taskPath = path.join(rootDir, 'replaceTokens.js'); 8 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 9 | 10 | // set up a tmp file for the test 11 | var workingFolder = path.join(__dirname, "working"); 12 | if (!fs.existsSync(workingFolder)) { 13 | fs.mkdirSync(workingFolder); 14 | } 15 | var tmpFile = path.join(workingFolder, "appsettings.config"); 16 | 17 | // provide answers for task mock 18 | let a: ma.TaskLibAnswers = { 19 | "checkPath": { 20 | "working": true 21 | }, 22 | "findMatch": { 23 | "*.config" : [ tmpFile ] 24 | } 25 | }; 26 | tmr.setAnswers(a); 27 | 28 | fs.writeFile(tmpFile, ` 29 | 30 | 31 | 32 | 33 | 34 | `, 35 | (err) => { 36 | 37 | // set inputs 38 | tmr.setInput('sourcePath', "working"); 39 | tmr.setInput('filePattern', '*.config'); 40 | tmr.setInput('tokenRegex', '@@(\\w+)@@'); 41 | 42 | // set variables 43 | process.env["CUSTOM_BUILDMAJORNUM"] = "1"; 44 | process.env["CUSTOM_BUILDMINORNUM"] = "2"; 45 | process.env["CUSTOM_BUILDPATCHNUM"] = "3"; 46 | 47 | tmr.run(); 48 | 49 | // validate the replacement 50 | let actual = fs.readFileSync(tmpFile).toString(); 51 | 52 | var expected = ` 53 | 54 | 55 | 56 | 57 | 58 | `; 59 | 60 | if (actual.trim() !== expected.trim()) { 61 | console.log(actual); 62 | console.error("Replacement failed."); 63 | } else { 64 | console.log("Replacement succeeded!") 65 | } 66 | }); -------------------------------------------------------------------------------- /test/replaceTokens/test-dotTokens.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const fs = require("fs"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'ReplaceTokens'); 7 | let taskPath = path.join(rootDir, 'replaceTokens.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // set up a tmp file for the test 10 | var workingFolder = path.join(__dirname, "working"); 11 | if (!fs.existsSync(workingFolder)) { 12 | fs.mkdirSync(workingFolder); 13 | } 14 | var tmpFile = path.join(workingFolder, "appsettings.config"); 15 | // provide answers for task mock 16 | let a = { 17 | "checkPath": { 18 | "working": true 19 | }, 20 | "findMatch": { 21 | "appsettings.json": [tmpFile] 22 | } 23 | }; 24 | tmr.setAnswers(a); 25 | fs.writeFile(tmpFile, ` 26 | { 27 | "ConnectionStrings": { 28 | "DefaultConnection": "__ConnectionStrings.DefaultConnection__" 29 | }, 30 | "Tricky": { 31 | "Gollum": "__Tricky.Gollum__", 32 | "Hobbit": "__Tricky.Hobbit__" 33 | }, 34 | "Logging": { 35 | "IncludeScopes": false, 36 | "LogLevel": { 37 | "Default": "Debug", 38 | "System": "Information", 39 | "Microsoft": "Information" 40 | } 41 | } 42 | } 43 | `, (err) => { 44 | // set inputs 45 | tmr.setInput('sourcePath', "working"); 46 | tmr.setInput('filePattern', 'appsettings.json'); 47 | tmr.setInput('tokenRegex', '__(\\w+[\\.\\w+]*\\[?\\]?)__'); 48 | // set variables 49 | process.env["CONNECTIONSTRINGS_DEFAULTCONNECTION"] = "testing"; 50 | process.env["TRICKY_GOLLUM"] = "Gollum2"; 51 | process.env["TRICKY_HOBBIT"] = "Sam"; 52 | tmr.run(); 53 | // validate the replacement 54 | let actual = fs.readFileSync(tmpFile).toString(); 55 | var expected = ` 56 | { 57 | "ConnectionStrings": { 58 | "DefaultConnection": "testing" 59 | }, 60 | "Tricky": { 61 | "Gollum": "Gollum2", 62 | "Hobbit": "Sam" 63 | }, 64 | "Logging": { 65 | "IncludeScopes": false, 66 | "LogLevel": { 67 | "Default": "Debug", 68 | "System": "Information", 69 | "Microsoft": "Information" 70 | } 71 | } 72 | } 73 | `; 74 | if (actual.trim() !== expected.trim()) { 75 | console.log(actual); 76 | console.error("Replacement failed."); 77 | } 78 | else { 79 | console.log("Replacement succeeded!"); 80 | } 81 | }); 82 | //# sourceMappingURL=test-dotTokens.js.map -------------------------------------------------------------------------------- /test/replaceTokens/test-dotTokens.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import fs = require('fs'); 5 | 6 | let rootDir = path.join(__dirname, '../../Tasks', 'ReplaceTokens'); 7 | let taskPath = path.join(rootDir, 'replaceTokens.js'); 8 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 9 | 10 | // set up a tmp file for the test 11 | var workingFolder = path.join(__dirname, "working"); 12 | if (!fs.existsSync(workingFolder)) { 13 | fs.mkdirSync(workingFolder); 14 | } 15 | var tmpFile = path.join(workingFolder, "appsettings.config"); 16 | 17 | // provide answers for task mock 18 | let a: ma.TaskLibAnswers = { 19 | "checkPath": { 20 | "working": true 21 | }, 22 | "findMatch": { 23 | "appsettings.json" : [ tmpFile ] 24 | } 25 | }; 26 | tmr.setAnswers(a); 27 | 28 | fs.writeFile(tmpFile, ` 29 | { 30 | "ConnectionStrings": { 31 | "DefaultConnection": "__ConnectionStrings.DefaultConnection__" 32 | }, 33 | "Tricky": { 34 | "Gollum": "__Tricky.Gollum__", 35 | "Hobbit": "__Tricky.Hobbit__" 36 | }, 37 | "Logging": { 38 | "IncludeScopes": false, 39 | "LogLevel": { 40 | "Default": "Debug", 41 | "System": "Information", 42 | "Microsoft": "Information" 43 | } 44 | } 45 | } 46 | `, 47 | (err) => { 48 | 49 | // set inputs 50 | tmr.setInput('sourcePath', "working"); 51 | tmr.setInput('filePattern', 'appsettings.json'); 52 | tmr.setInput('tokenRegex', '__(\\w+[\\.\\w+]*\\[?\\]?)__'); 53 | 54 | // set variables 55 | process.env["CONNECTIONSTRINGS_DEFAULTCONNECTION"] = "testing"; 56 | process.env["TRICKY_GOLLUM"] = "Gollum2"; 57 | process.env["TRICKY_HOBBIT"] = "Sam"; 58 | 59 | tmr.run(); 60 | 61 | // validate the replacement 62 | let actual = fs.readFileSync(tmpFile).toString(); 63 | 64 | var expected = ` 65 | { 66 | "ConnectionStrings": { 67 | "DefaultConnection": "testing" 68 | }, 69 | "Tricky": { 70 | "Gollum": "Gollum2", 71 | "Hobbit": "Sam" 72 | }, 73 | "Logging": { 74 | "IncludeScopes": false, 75 | "LogLevel": { 76 | "Default": "Debug", 77 | "System": "Information", 78 | "Microsoft": "Information" 79 | } 80 | } 81 | } 82 | `; 83 | 84 | if (actual.trim() !== expected.trim()) { 85 | console.log(actual); 86 | console.error("Replacement failed."); 87 | } else { 88 | console.log("Replacement succeeded!") 89 | } 90 | }); -------------------------------------------------------------------------------- /test/replaceTokens/test-emptyPath.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const fs = require("fs"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'ReplaceTokens'); 7 | let taskPath = path.join(rootDir, 'replaceTokens.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // set up a tmp file for the test 10 | var workingFolder = path.join(__dirname, "working"); 11 | if (!fs.existsSync(workingFolder)) { 12 | fs.mkdirSync(workingFolder); 13 | } 14 | var tmpFile = path.join(workingFolder, "file.config"); 15 | // provide answers for task mock 16 | console.log("----------------- " + workingFolder); 17 | let a = { 18 | "checkPath": { 19 | "working": true 20 | }, 21 | "findMatch": { 22 | "*.config": [tmpFile] 23 | } 24 | }; 25 | tmr.setAnswers(a); 26 | fs.writeFile(tmpFile, ` 27 | 28 | 29 | 30 | 31 | 32 | 33 | `, (err) => { 34 | // set inputs 35 | tmr.setInput('filePattern', '*.config'); 36 | tmr.setInput('tokenRegex', '__(\\w+)__'); 37 | // set variables 38 | process.env["COOLKEY"] = "MyCoolKey"; 39 | process.env["SECRET_Secret1"] = "supersecret1"; 40 | process.env["BUILD_SOURCESDIRECTORY"] = "working"; 41 | tmr.run(); 42 | // validate the replacement 43 | let actual = fs.readFileSync(tmpFile).toString(); 44 | var expected = ` 45 | 46 | 47 | 48 | 49 | 50 | 51 | `; 52 | if (actual.trim() !== expected.trim()) { 53 | console.log(actual); 54 | console.error("Replacement failed."); 55 | } 56 | else { 57 | console.log("Replacement succeeded!"); 58 | } 59 | }); 60 | //# sourceMappingURL=test-emptyPath.js.map -------------------------------------------------------------------------------- /test/replaceTokens/test-emptyPath.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import assert = require('assert'); 5 | import fs = require('fs'); 6 | 7 | let rootDir = path.join(__dirname, '../../Tasks', 'ReplaceTokens'); 8 | let taskPath = path.join(rootDir, 'replaceTokens.js'); 9 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 10 | 11 | // set up a tmp file for the test 12 | var workingFolder = path.join(__dirname, "working"); 13 | if (!fs.existsSync(workingFolder)) { 14 | fs.mkdirSync(workingFolder); 15 | } 16 | var tmpFile = path.join(workingFolder, "file.config"); 17 | 18 | // provide answers for task mock 19 | console.log("----------------- " + workingFolder) 20 | let a: ma.TaskLibAnswers = { 21 | "checkPath": { 22 | "working": true 23 | }, 24 | "findMatch": { 25 | "*.config" : [ tmpFile ] 26 | } 27 | }; 28 | tmr.setAnswers(a); 29 | 30 | fs.writeFile(tmpFile, ` 31 | 32 | 33 | 34 | 35 | 36 | 37 | `, 38 | (err) => { 39 | 40 | // set inputs 41 | tmr.setInput('filePattern', '*.config'); 42 | tmr.setInput('tokenRegex', '__(\\w+)__'); 43 | 44 | // set variables 45 | process.env["COOLKEY"] = "MyCoolKey"; 46 | process.env["SECRET_Secret1"] = "supersecret1"; 47 | process.env["BUILD_SOURCESDIRECTORY"] = "working"; 48 | tmr.run(); 49 | 50 | // validate the replacement 51 | let actual = fs.readFileSync(tmpFile).toString(); 52 | var expected = ` 53 | 54 | 55 | 56 | 57 | 58 | 59 | `; 60 | 61 | if (actual.trim() !== expected.trim()) { 62 | console.log(actual); 63 | console.error("Replacement failed."); 64 | } else { 65 | console.log("Replacement succeeded!") 66 | } 67 | }); -------------------------------------------------------------------------------- /test/replaceTokens/test-normalInputs.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const fs = require("fs"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'ReplaceTokens'); 7 | let taskPath = path.join(rootDir, 'replaceTokens.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // set up a tmp file for the test 10 | var workingFolder = path.join(__dirname, "working"); 11 | if (!fs.existsSync(workingFolder)) { 12 | fs.mkdirSync(workingFolder); 13 | } 14 | var tmpFile = path.join(workingFolder, "file.config"); 15 | // provide answers for task mock 16 | let a = { 17 | "checkPath": { 18 | "working": true 19 | }, 20 | "findMatch": { 21 | "*.config": [tmpFile] 22 | } 23 | }; 24 | tmr.setAnswers(a); 25 | fs.writeFile(tmpFile, ` 26 | 27 | 28 | 29 | 30 | 31 | 32 | `, (err) => { 33 | // set inputs 34 | tmr.setInput('sourcePath', "working"); 35 | tmr.setInput('filePattern', '*.config'); 36 | tmr.setInput('tokenRegex', '__(\\w+)__'); 37 | // set variables 38 | process.env["COOLKEY"] = "MyCoolKey"; 39 | process.env["SECRET_Secret1"] = "supersecret1"; 40 | tmr.run(); 41 | // validate the replacement 42 | let actual = fs.readFileSync(tmpFile).toString(); 43 | var expected = ` 44 | 45 | 46 | 47 | 48 | 49 | 50 | `; 51 | if (actual.trim() !== expected.trim()) { 52 | console.log(actual); 53 | console.error("Replacement failed."); 54 | } 55 | else { 56 | console.log("Replacement succeeded!"); 57 | } 58 | }); 59 | //# sourceMappingURL=test-normalInputs.js.map -------------------------------------------------------------------------------- /test/replaceTokens/test-normalInputs.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import fs = require('fs'); 5 | 6 | let rootDir = path.join(__dirname, '../../Tasks', 'ReplaceTokens'); 7 | let taskPath = path.join(rootDir, 'replaceTokens.js'); 8 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 9 | 10 | // set up a tmp file for the test 11 | var workingFolder = path.join(__dirname, "working"); 12 | if (!fs.existsSync(workingFolder)) { 13 | fs.mkdirSync(workingFolder); 14 | } 15 | var tmpFile = path.join(workingFolder, "file.config"); 16 | 17 | // provide answers for task mock 18 | let a: ma.TaskLibAnswers = { 19 | "checkPath": { 20 | "working": true 21 | }, 22 | "findMatch": { 23 | "*.config" : [ tmpFile ] 24 | } 25 | }; 26 | tmr.setAnswers(a); 27 | 28 | fs.writeFile(tmpFile, ` 29 | 30 | 31 | 32 | 33 | 34 | 35 | `, 36 | (err) => { 37 | 38 | // set inputs 39 | tmr.setInput('sourcePath', "working"); 40 | tmr.setInput('filePattern', '*.config'); 41 | tmr.setInput('tokenRegex', '__(\\w+)__'); 42 | 43 | // set variables 44 | process.env["COOLKEY"] = "MyCoolKey"; 45 | process.env["SECRET_Secret1"] = "supersecret1"; 46 | 47 | tmr.run(); 48 | 49 | // validate the replacement 50 | let actual = fs.readFileSync(tmpFile).toString(); 51 | var expected = ` 52 | 53 | 54 | 55 | 56 | 57 | 58 | `; 59 | 60 | if (actual.trim() !== expected.trim()) { 61 | console.log(actual); 62 | console.error("Replacement failed."); 63 | } else { 64 | console.log("Replacement succeeded!") 65 | } 66 | }); 67 | -------------------------------------------------------------------------------- /test/replaceTokens/test-warnings-as-error-off.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const fs = require("fs"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'ReplaceTokens'); 7 | let taskPath = path.join(rootDir, 'replaceTokens.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // set up a tmp file for the test 10 | var workingFolder = path.join(__dirname, "working"); 11 | if (!fs.existsSync(workingFolder)) { 12 | fs.mkdirSync(workingFolder); 13 | } 14 | var tmpFile = path.join(workingFolder, "file.config"); 15 | // provide answers for task mock 16 | let a = { 17 | "checkPath": { 18 | "working": true 19 | }, 20 | "findMatch": { 21 | "*.config": [tmpFile] 22 | } 23 | }; 24 | tmr.setAnswers(a); 25 | fs.writeFile(tmpFile, ` 26 | 27 | 28 | 29 | 30 | 31 | 32 | `, (err) => { 33 | // set inputs 34 | tmr.setInput('sourcePath', "working"); 35 | tmr.setInput('filePattern', '*.config'); 36 | tmr.setInput('tokenRegex', '__(\\w+)__'); 37 | // set variables 38 | // Env var not set -> process.env["COOLKEY"] = "MyCoolKey"; 39 | process.env["SECRET_Secret1"] = "supersecret1"; 40 | tmr.run(); 41 | }); 42 | //# sourceMappingURL=test-warnings-as-error-off.js.map -------------------------------------------------------------------------------- /test/replaceTokens/test-warnings-as-error-off.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import fs = require('fs'); 5 | 6 | let rootDir = path.join(__dirname, '../../Tasks', 'ReplaceTokens'); 7 | let taskPath = path.join(rootDir, 'replaceTokens.js'); 8 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 9 | 10 | // set up a tmp file for the test 11 | var workingFolder = path.join(__dirname, "working"); 12 | if (!fs.existsSync(workingFolder)) { 13 | fs.mkdirSync(workingFolder); 14 | } 15 | var tmpFile = path.join(workingFolder, "file.config"); 16 | 17 | // provide answers for task mock 18 | let a: ma.TaskLibAnswers = { 19 | "checkPath": { 20 | "working": true 21 | }, 22 | "findMatch": { 23 | "*.config" : [ tmpFile ] 24 | } 25 | }; 26 | tmr.setAnswers(a); 27 | 28 | fs.writeFile(tmpFile, ` 29 | 30 | 31 | 32 | 33 | 34 | 35 | `, 36 | (err) => { 37 | 38 | // set inputs 39 | tmr.setInput('sourcePath', "working"); 40 | tmr.setInput('filePattern', '*.config'); 41 | tmr.setInput('tokenRegex', '__(\\w+)__'); 42 | 43 | // set variables 44 | // Env var not set -> process.env["COOLKEY"] = "MyCoolKey"; 45 | process.env["SECRET_Secret1"] = "supersecret1"; 46 | 47 | tmr.run(); 48 | }); 49 | -------------------------------------------------------------------------------- /test/replaceTokens/test-warnings-as-errors-on.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const fs = require("fs"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'ReplaceTokens'); 7 | let taskPath = path.join(rootDir, 'replaceTokens.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // set up a tmp file for the test 10 | var workingFolder = path.join(__dirname, "working"); 11 | if (!fs.existsSync(workingFolder)) { 12 | fs.mkdirSync(workingFolder); 13 | } 14 | var tmpFile = path.join(workingFolder, "file.config"); 15 | // provide answers for task mock 16 | let a = { 17 | "checkPath": { 18 | "working": true 19 | }, 20 | "findMatch": { 21 | "*.config": [tmpFile] 22 | } 23 | }; 24 | tmr.setAnswers(a); 25 | fs.writeFile(tmpFile, ` 26 | 27 | 28 | 29 | 30 | 31 | 32 | `, (err) => { 33 | // set inputs 34 | tmr.setInput('sourcePath', "working"); 35 | tmr.setInput('filePattern', '*.config'); 36 | tmr.setInput('warningsAsErrors', 'true'); 37 | tmr.setInput('tokenRegex', '__(\\w+)__'); 38 | // set variables 39 | // Env var not set -> process.env["COOLKEY"] = "MyCoolKey"; 40 | process.env["SECRET_Secret1"] = "supersecret1"; 41 | tmr.run(); 42 | }); 43 | //# sourceMappingURL=test-warnings-as-errors-on.js.map -------------------------------------------------------------------------------- /test/replaceTokens/test-warnings-as-errors-on.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import fs = require('fs'); 5 | 6 | let rootDir = path.join(__dirname, '../../Tasks', 'ReplaceTokens'); 7 | let taskPath = path.join(rootDir, 'replaceTokens.js'); 8 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 9 | 10 | // set up a tmp file for the test 11 | var workingFolder = path.join(__dirname, "working"); 12 | if (!fs.existsSync(workingFolder)) { 13 | fs.mkdirSync(workingFolder); 14 | } 15 | var tmpFile = path.join(workingFolder, "file.config"); 16 | 17 | // provide answers for task mock 18 | let a: ma.TaskLibAnswers = { 19 | "checkPath": { 20 | "working": true 21 | }, 22 | "findMatch": { 23 | "*.config" : [ tmpFile ] 24 | } 25 | }; 26 | tmr.setAnswers(a); 27 | 28 | fs.writeFile(tmpFile, ` 29 | 30 | 31 | 32 | 33 | 34 | 35 | `, 36 | (err) => { 37 | 38 | // set inputs 39 | tmr.setInput('sourcePath', "working"); 40 | tmr.setInput('filePattern', '*.config'); 41 | tmr.setInput('warningsAsErrors', 'true'); 42 | tmr.setInput('tokenRegex', '__(\\w+)__'); 43 | 44 | // set variables 45 | // Env var not set -> process.env["COOLKEY"] = "MyCoolKey"; 46 | process.env["SECRET_Secret1"] = "supersecret1"; 47 | 48 | tmr.run(); 49 | }); 50 | -------------------------------------------------------------------------------- /test/replaceTokens/working/appsettings.config: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "ConnectionStrings": { 4 | "DefaultConnection": "testing" 5 | }, 6 | "Tricky": { 7 | "Gollum": "Gollum2", 8 | "Hobbit": "Sam" 9 | }, 10 | "Logging": { 11 | "IncludeScopes": false, 12 | "LogLevel": { 13 | "Default": "Debug", 14 | "System": "Information", 15 | "Microsoft": "Information" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/replaceTokens/working/file.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/replaceTokens/working/file.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "Auth": { 4 | "ClientSecret": "Secret", 5 | "ValidAudiences": [ 6 | "a","b","c" 7 | ], 8 | "ConnectionStringKVSecretName": "someval" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/routeTraffic/mocks.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.getEndpointUrl = exports.getEndpointDataParameter = exports.getEndpointAuthorizationParameter = exports.TestHttpClient = exports.HttpClientResponse = void 0; 4 | class HttpClientResponse { 5 | constructor(message) { 6 | this.message = message; 7 | } 8 | readBody() { 9 | return Promise.resolve(this.message.body); 10 | } 11 | } 12 | exports.HttpClientResponse = HttpClientResponse; 13 | var TestHttpClient; 14 | (function (TestHttpClient) { 15 | TestHttpClient.responses = {}; 16 | TestHttpClient.calls = []; 17 | function HttpClient(agent) { 18 | console.log("--- MOCK: creating mock httpClient"); 19 | return { 20 | post: (url, data, headers) => { 21 | TestHttpClient.calls.push({ 22 | method: "push", 23 | url: url, 24 | data: data, 25 | headers: headers 26 | }); 27 | return Promise.resolve(TestHttpClient.responses.find(r => r.url === url).response); 28 | }, 29 | put: (url, data, headers) => { 30 | TestHttpClient.calls.push({ 31 | method: "put", 32 | url: url, 33 | data: data, 34 | headers: headers 35 | }); 36 | return Promise.resolve(TestHttpClient.responses.find(r => r.url === url).response); 37 | } 38 | }; 39 | } 40 | TestHttpClient.HttpClient = HttpClient; 41 | })(TestHttpClient = exports.TestHttpClient || (exports.TestHttpClient = {})); 42 | let endPointParameters = { 43 | serviceprincipalid: "spId", 44 | serviceprincipalkey: "spKey", 45 | tenantid: "tenantId", 46 | }; 47 | let endPointData = { 48 | subscriptionid: "subId", 49 | environmentAuthorityUrl: "https://manage.me.fake/" 50 | }; 51 | function getEndpointAuthorizationParameter(name, key, required) { 52 | return endPointParameters[key]; 53 | } 54 | exports.getEndpointAuthorizationParameter = getEndpointAuthorizationParameter; 55 | function getEndpointDataParameter(name, key, required) { 56 | return endPointData[key]; 57 | } 58 | exports.getEndpointDataParameter = getEndpointDataParameter; 59 | function getEndpointUrl(name, required) { 60 | return "https://manage.me.fake/"; 61 | } 62 | exports.getEndpointUrl = getEndpointUrl; 63 | //# sourceMappingURL=mocks.js.map -------------------------------------------------------------------------------- /test/routeTraffic/mocks.ts: -------------------------------------------------------------------------------- 1 | import tl = require('azure-pipelines-task-lib/task'); 2 | 3 | export interface IIncomingMessage { 4 | statusCode?: number; 5 | statusMessage?: string; 6 | body: string; 7 | } 8 | 9 | export class HttpClientResponse { 10 | constructor(public message: IIncomingMessage) { 11 | } 12 | 13 | readBody() { 14 | return Promise.resolve(this.message.body); 15 | } 16 | } 17 | 18 | export interface IResponse { 19 | url: string, 20 | response: Promise 21 | } 22 | 23 | export interface ICall { 24 | method: string, 25 | url: string, 26 | data: any, 27 | headers: any 28 | } 29 | 30 | export module TestHttpClient { 31 | export var responses = {}; 32 | export var calls = []; 33 | 34 | export function HttpClient(agent) { 35 | console.log("--- MOCK: creating mock httpClient"); 36 | 37 | return { 38 | post: (url: string, data: string, headers) => { 39 | calls.push({ 40 | method: "push", 41 | url: url, 42 | data: data, 43 | headers: headers 44 | }); 45 | return Promise.resolve(responses.find(r => r.url === url).response); 46 | }, 47 | put: (url: string, data: string, headers) => { 48 | calls.push({ 49 | method: "put", 50 | url: url, 51 | data: data, 52 | headers: headers 53 | }); 54 | return Promise.resolve(responses.find(r => r.url === url).response); 55 | } 56 | }; 57 | } 58 | } 59 | 60 | let endPointParameters = { 61 | serviceprincipalid: "spId", 62 | serviceprincipalkey: "spKey", 63 | tenantid: "tenantId", 64 | } 65 | 66 | let endPointData = { 67 | subscriptionid: "subId", 68 | environmentAuthorityUrl: "https://manage.me.fake/" 69 | } 70 | 71 | export function getEndpointAuthorizationParameter(name: string, key: string, required: boolean) { 72 | return endPointParameters[key]; 73 | } 74 | 75 | export function getEndpointDataParameter(name: string, key: string, required: boolean) { 76 | return endPointData[key]; 77 | } 78 | 79 | export function getEndpointUrl(name: string, required: boolean) { 80 | return "https://manage.me.fake/"; 81 | } -------------------------------------------------------------------------------- /test/routeTraffic/test-handles-authFailure.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const mocks = require("./mocks"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'RouteTraffic'); 7 | let taskPath = path.join(rootDir, 'routeTraffic.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // provide fake responses 10 | mocks.TestHttpClient.responses = [ 11 | { 12 | url: "https://manage.me.fake/tenantId/oauth2/token/", 13 | response: Promise.resolve(new mocks.HttpClientResponse({ 14 | statusCode: 401, 15 | statusMessage: "access denied", 16 | body: null 17 | })) 18 | } 19 | ]; 20 | // provide mocks 21 | tmr.registerMock('typed-rest-client/HttpClient', mocks.TestHttpClient); 22 | tmr.registerMockExport('getEndpointAuthorizationParameter', mocks.getEndpointAuthorizationParameter); 23 | tmr.registerMockExport('getEndpointDataParameter', mocks.getEndpointDataParameter); 24 | tmr.registerMockExport('getEndpointUrl', mocks.getEndpointUrl); 25 | // set variables 26 | process.env["AZURE_HTTP_USER_AGENT"] = "mock-user-agent"; 27 | // set inputs 28 | tmr.setInput('ConnectedServiceName', "MyAzureEndpoint"); 29 | tmr.setInput('Slot', "blue"); 30 | tmr.setInput('WebAppName', "test-app"); 31 | tmr.setInput('ResourceGroupName', "test-app"); 32 | tmr.setInput('percentTraffic', "22.345"); 33 | tmr.run(); 34 | //# sourceMappingURL=test-handles-authFailure.js.map -------------------------------------------------------------------------------- /test/routeTraffic/test-handles-authFailure.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import mocks = require('./mocks'); 5 | 6 | let rootDir = path.join(__dirname, '../../Tasks', 'RouteTraffic'); 7 | let taskPath = path.join(rootDir, 'routeTraffic.js'); 8 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 9 | 10 | // provide fake responses 11 | mocks.TestHttpClient.responses = [ 12 | { 13 | url: "https://manage.me.fake/tenantId/oauth2/token/", 14 | response: Promise.resolve(new mocks.HttpClientResponse({ 15 | statusCode: 401, 16 | statusMessage: "access denied", 17 | body: null 18 | })) 19 | } 20 | ]; 21 | 22 | // provide mocks 23 | tmr.registerMock('typed-rest-client/HttpClient', mocks.TestHttpClient); 24 | tmr.registerMockExport('getEndpointAuthorizationParameter', mocks.getEndpointAuthorizationParameter); 25 | tmr.registerMockExport('getEndpointDataParameter', mocks.getEndpointDataParameter); 26 | tmr.registerMockExport('getEndpointUrl', mocks.getEndpointUrl); 27 | 28 | // set variables 29 | process.env["AZURE_HTTP_USER_AGENT"] = "mock-user-agent"; 30 | 31 | // set inputs 32 | tmr.setInput('ConnectedServiceName', "MyAzureEndpoint"); 33 | tmr.setInput('Slot', "blue"); 34 | tmr.setInput('WebAppName', "test-app"); 35 | tmr.setInput('ResourceGroupName', "test-app"); 36 | tmr.setInput('percentTraffic', "22.345"); 37 | 38 | tmr.run(); -------------------------------------------------------------------------------- /test/routeTraffic/test-handles-callFailure.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const mocks = require("./mocks"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'RouteTraffic'); 7 | let taskPath = path.join(rootDir, 'routeTraffic.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // provide fake responses 10 | mocks.TestHttpClient.responses = [ 11 | { 12 | url: "https://manage.me.fake/tenantId/oauth2/token/", 13 | response: Promise.resolve(new mocks.HttpClientResponse({ 14 | statusCode: 200, 15 | statusMessage: "ok", 16 | body: JSON.stringify({ 17 | access_token: "fake-token-issue-from-token-endpoint" 18 | }) 19 | })) 20 | }, 21 | { 22 | url: "https://manage.me.fake/subscriptions/subId/resourceGroups/test-app/providers/Microsoft.Web/sites/test-app/config/web?api-version=2016-08-01", 23 | response: Promise.resolve(new mocks.HttpClientResponse({ 24 | statusCode: 500, 25 | statusMessage: "something broke", 26 | body: "" 27 | })) 28 | } 29 | ]; 30 | // provide mocks 31 | tmr.registerMock('typed-rest-client/HttpClient', mocks.TestHttpClient); 32 | tmr.registerMockExport('getEndpointAuthorizationParameter', mocks.getEndpointAuthorizationParameter); 33 | tmr.registerMockExport('getEndpointDataParameter', mocks.getEndpointDataParameter); 34 | tmr.registerMockExport('getEndpointUrl', mocks.getEndpointUrl); 35 | // set variables 36 | process.env["AZURE_HTTP_USER_AGENT"] = "mock-user-agent"; 37 | // set inputs 38 | tmr.setInput('ConnectedServiceName', "MyAzureEndpoint"); 39 | tmr.setInput('Slot', "blue"); 40 | tmr.setInput('WebAppName', "test-app"); 41 | tmr.setInput('ResourceGroupName', "test-app"); 42 | tmr.setInput('percentTraffic', "22.345"); 43 | tmr.run(); 44 | //# sourceMappingURL=test-handles-callFailure.js.map -------------------------------------------------------------------------------- /test/routeTraffic/test-handles-callFailure.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import mocks = require('./mocks'); 5 | 6 | let rootDir = path.join(__dirname, '../../Tasks', 'RouteTraffic'); 7 | let taskPath = path.join(rootDir, 'routeTraffic.js'); 8 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 9 | 10 | // provide fake responses 11 | mocks.TestHttpClient.responses = [ 12 | { 13 | url: "https://manage.me.fake/tenantId/oauth2/token/", 14 | response: Promise.resolve(new mocks.HttpClientResponse({ 15 | statusCode: 200, 16 | statusMessage: "ok", 17 | body: JSON.stringify({ 18 | access_token : "fake-token-issue-from-token-endpoint" 19 | }) 20 | })) 21 | }, 22 | { 23 | url: "https://manage.me.fake/subscriptions/subId/resourceGroups/test-app/providers/Microsoft.Web/sites/test-app/config/web?api-version=2016-08-01", 24 | response: Promise.resolve(new mocks.HttpClientResponse({ 25 | statusCode: 500, 26 | statusMessage: "something broke", 27 | body: "" 28 | })) 29 | } 30 | ]; 31 | 32 | // provide mocks 33 | tmr.registerMock('typed-rest-client/HttpClient', mocks.TestHttpClient); 34 | tmr.registerMockExport('getEndpointAuthorizationParameter', mocks.getEndpointAuthorizationParameter); 35 | tmr.registerMockExport('getEndpointDataParameter', mocks.getEndpointDataParameter); 36 | tmr.registerMockExport('getEndpointUrl', mocks.getEndpointUrl); 37 | 38 | // set variables 39 | process.env["AZURE_HTTP_USER_AGENT"] = "mock-user-agent"; 40 | 41 | // set inputs 42 | tmr.setInput('ConnectedServiceName', "MyAzureEndpoint"); 43 | tmr.setInput('Slot', "blue"); 44 | tmr.setInput('WebAppName', "test-app"); 45 | tmr.setInput('ResourceGroupName', "test-app"); 46 | tmr.setInput('percentTraffic', "22.345"); 47 | 48 | tmr.run(); -------------------------------------------------------------------------------- /test/tagBuild/mockErrorWebApi.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.MockWebApi = void 0; 4 | var MockWebApi; 5 | (function (MockWebApi) { 6 | MockWebApi.calledBearer = false; 7 | MockWebApi.taggerCall = { 8 | callType: '', 9 | tags: [], 10 | id: 0, 11 | project: '' 12 | }; 13 | var mockCredHandler = { 14 | prepareRequest: (options) => { }, 15 | canHandleAuthentication: (res) => true, 16 | handleAuthentication: (httpClient, protocol, options, objs, finalCallback) => { } 17 | }; 18 | function getBearerHandler(token) { 19 | console.log("--- MOCK: return fake bearer handler"); 20 | MockWebApi.calledBearer = true; 21 | return mockCredHandler; 22 | } 23 | MockWebApi.getBearerHandler = getBearerHandler; 24 | class WebApi { 25 | constructor(tpcUri, credHandler) { 26 | } 27 | getLocationsApi() { 28 | return { 29 | getResourceArea(areaId) { 30 | return Promise.resolve({ 31 | locationUrl: "theUrl" 32 | }); 33 | } 34 | }; 35 | } 36 | getBuildApi() { 37 | return { 38 | addBuildTags(tags, teamProject, buildId) { 39 | console.log("--- MOCK: calling buildAPI.addBuildTags"); 40 | MockWebApi.taggerCall.callType = 'Build'; 41 | MockWebApi.taggerCall.tags = tags; 42 | MockWebApi.taggerCall.project = teamProject; 43 | MockWebApi.taggerCall.id = buildId; 44 | return Promise.reject("Something went wrong with build api call"); 45 | } 46 | }; 47 | } 48 | getReleaseApi(resourceUrl) { 49 | return { 50 | addReleaseTags(tags, teamProject, releaseId) { 51 | console.log("--- MOCK: calling releaseAPI.addReleaseTags"); 52 | MockWebApi.taggerCall.callType = 'Release'; 53 | MockWebApi.taggerCall.tags = tags; 54 | MockWebApi.taggerCall.project = teamProject; 55 | MockWebApi.taggerCall.id = releaseId; 56 | return Promise.reject("Something went wrong with release api call"); 57 | } 58 | }; 59 | } 60 | } 61 | MockWebApi.WebApi = WebApi; 62 | })(MockWebApi = exports.MockWebApi || (exports.MockWebApi = {})); 63 | //# sourceMappingURL=mockErrorWebApi.js.map -------------------------------------------------------------------------------- /test/tagBuild/mockErrorWebApi.ts: -------------------------------------------------------------------------------- 1 | export module MockWebApi { 2 | export var calledBearer = false; 3 | export var taggerCall = { 4 | callType: '', 5 | tags: [], 6 | id: 0, 7 | project: '' 8 | } 9 | 10 | var mockCredHandler = { // a mock IRequestHandler 11 | prepareRequest: (options: any) => { }, 12 | canHandleAuthentication: (res) => true, 13 | handleAuthentication: (httpClient: any, protocol: any, options: any, objs: any, finalCallback: any) => { } 14 | }; 15 | 16 | export function getBearerHandler(token) { 17 | console.log("--- MOCK: return fake bearer handler"); 18 | calledBearer = true; 19 | return mockCredHandler; 20 | } 21 | 22 | export class WebApi { 23 | constructor(tpcUri, credHandler) { 24 | } 25 | 26 | getLocationsApi() { 27 | return { 28 | getResourceArea(areaId: string) { 29 | return Promise.resolve({ 30 | locationUrl: "theUrl" 31 | }); 32 | } 33 | }; 34 | } 35 | 36 | getBuildApi() { 37 | return { 38 | addBuildTags(tags: string[], teamProject: string, buildId: number) { 39 | console.log("--- MOCK: calling buildAPI.addBuildTags"); 40 | taggerCall.callType = 'Build'; 41 | taggerCall.tags = tags; 42 | taggerCall.project = teamProject; 43 | taggerCall.id = buildId; 44 | return Promise.reject("Something went wrong with build api call"); 45 | } 46 | }; 47 | } 48 | 49 | getReleaseApi(resourceUrl?: string) { 50 | return { 51 | addReleaseTags(tags: string[], teamProject: string, releaseId: number) { 52 | console.log("--- MOCK: calling releaseAPI.addReleaseTags"); 53 | taggerCall.callType = 'Release'; 54 | taggerCall.tags = tags; 55 | taggerCall.project = teamProject; 56 | taggerCall.id = releaseId; 57 | return Promise.reject("Something went wrong with release api call"); 58 | } 59 | }; 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /test/tagBuild/mockWebApi.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.MockWebApi = void 0; 4 | var MockWebApi; 5 | (function (MockWebApi) { 6 | MockWebApi.calledBearer = false; 7 | MockWebApi.taggerCall = { 8 | callType: '', 9 | tags: [], 10 | id: 0, 11 | project: '' 12 | }; 13 | var mockCredHandler = { 14 | prepareRequest: (options) => { }, 15 | canHandleAuthentication: (res) => true, 16 | handleAuthentication: (httpClient, protocol, options, objs, finalCallback) => { } 17 | }; 18 | function getBearerHandler(token) { 19 | console.log("--- MOCK: return fake bearer handler"); 20 | MockWebApi.calledBearer = true; 21 | return mockCredHandler; 22 | } 23 | MockWebApi.getBearerHandler = getBearerHandler; 24 | class WebApi { 25 | constructor(tpcUri, credHandler) { 26 | } 27 | getLocationsApi() { 28 | return Promise.resolve({ 29 | getResourceArea(areaId) { 30 | return Promise.resolve({ 31 | locationUrl: "theUrl" 32 | }); 33 | } 34 | }); 35 | } 36 | getBuildApi() { 37 | return Promise.resolve({ 38 | addBuildTags(tags, teamProject, buildId) { 39 | console.log("--- MOCK: calling buildAPI.addBuildTags"); 40 | MockWebApi.taggerCall.callType = 'Build'; 41 | MockWebApi.taggerCall.tags = tags; 42 | MockWebApi.taggerCall.project = teamProject; 43 | MockWebApi.taggerCall.id = buildId; 44 | return Promise.resolve(tags); 45 | } 46 | }); 47 | } 48 | getReleaseApi(resourceUrl) { 49 | return Promise.resolve({ 50 | addReleaseTags(tags, teamProject, releaseId) { 51 | console.log("--- MOCK: calling releaseAPI.addReleaseTags"); 52 | MockWebApi.taggerCall.callType = 'Release'; 53 | MockWebApi.taggerCall.tags = tags; 54 | MockWebApi.taggerCall.project = teamProject; 55 | MockWebApi.taggerCall.id = releaseId; 56 | return Promise.resolve(tags); 57 | } 58 | }); 59 | } 60 | } 61 | MockWebApi.WebApi = WebApi; 62 | })(MockWebApi = exports.MockWebApi || (exports.MockWebApi = {})); 63 | //# sourceMappingURL=mockWebApi.js.map -------------------------------------------------------------------------------- /test/tagBuild/mockWebApi.ts: -------------------------------------------------------------------------------- 1 | import { ILocationsApi } from "azure-devops-node-api/LocationsApi"; 2 | import { IBuildApi } from "azure-devops-node-api/BuildApi"; 3 | import { IReleaseApi } from "azure-devops-node-api/ReleaseApi"; 4 | 5 | export module MockWebApi { 6 | export var calledBearer = false; 7 | export var taggerCall = { 8 | callType: '', 9 | tags: [], 10 | id: 0, 11 | project: '' 12 | } 13 | 14 | var mockCredHandler = { // a mock IRequestHandler 15 | prepareRequest: (options: any) => { }, 16 | canHandleAuthentication: (res) => true, 17 | handleAuthentication: (httpClient: any, protocol: any, options: any, objs: any, finalCallback: any) => { } 18 | }; 19 | 20 | export function getBearerHandler(token) { 21 | console.log("--- MOCK: return fake bearer handler"); 22 | calledBearer = true; 23 | return mockCredHandler; 24 | } 25 | 26 | export class WebApi { 27 | constructor(tpcUri, credHandler) { 28 | } 29 | 30 | getLocationsApi() { 31 | return Promise.resolve({ 32 | getResourceArea(areaId: string) { 33 | return Promise.resolve({ 34 | locationUrl: "theUrl" 35 | }); 36 | } 37 | }); 38 | } 39 | 40 | getBuildApi() { 41 | return Promise.resolve({ 42 | addBuildTags(tags: string[], teamProject: string, buildId: number) { 43 | console.log("--- MOCK: calling buildAPI.addBuildTags"); 44 | taggerCall.callType = 'Build'; 45 | taggerCall.tags = tags; 46 | taggerCall.project = teamProject; 47 | taggerCall.id = buildId; 48 | return Promise.resolve(tags); 49 | } 50 | }); 51 | } 52 | 53 | getReleaseApi(resourceUrl?: string) { 54 | return Promise.resolve({ 55 | addReleaseTags(tags: string[], teamProject: string, releaseId: number) { 56 | console.log("--- MOCK: calling releaseAPI.addReleaseTags"); 57 | taggerCall.callType = 'Release'; 58 | taggerCall.tags = tags; 59 | taggerCall.project = teamProject; 60 | taggerCall.id = releaseId; 61 | return Promise.resolve(tags); 62 | } 63 | }); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /test/tagBuild/test-build-noBuildId-fails.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const mocks = require("./mockWebApi"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'TagBuild'); 7 | let taskPath = path.join(rootDir, 'tagBuild.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 10 | // set variables 11 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 12 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 13 | process.env["BUILD_BUILDID"] = "-1"; // fake this since it's in the env from the 'real' build 14 | // set inputs 15 | tmr.setInput('tags', `tag1 16 | tag2`); 17 | tmr.setInput('type', 'Build'); 18 | tmr.run(); 19 | //# sourceMappingURL=test-build-noBuildId-fails.js.map -------------------------------------------------------------------------------- /test/tagBuild/test-build-noBuildId-fails.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import assert = require('assert'); 5 | import mocks = require('./mockWebApi'); 6 | 7 | let rootDir = path.join(__dirname, '../../Tasks', 'TagBuild'); 8 | let taskPath = path.join(rootDir, 'tagBuild.js'); 9 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 10 | 11 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 12 | 13 | // set variables 14 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 15 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 16 | process.env["BUILD_BUILDID"] = "-1"; // fake this since it's in the env from the 'real' build 17 | 18 | // set inputs 19 | tmr.setInput('tags', `tag1 20 | tag2`); 21 | tmr.setInput('type', 'Build'); 22 | 23 | tmr.run(); -------------------------------------------------------------------------------- /test/tagBuild/test-multiTag-succeeds.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const mocks = require("./mockWebApi"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'TagBuild'); 7 | let taskPath = path.join(rootDir, 'tagBuild.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 10 | // set variables 11 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 12 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 13 | process.env["BUILD_BUILDID"] = "1"; 14 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 15 | // set inputs 16 | tmr.setInput('tags', `tag1 17 | tag2`); 18 | tmr.setInput('type', 'Build'); 19 | tmr.run(); 20 | // need setTimeout because of async methods 21 | setTimeout(() => { 22 | if ("demo" !== mocks.MockWebApi.taggerCall.project || 23 | "Build" !== mocks.MockWebApi.taggerCall.callType || 24 | 1 !== mocks.MockWebApi.taggerCall.id || 25 | !mocks.MockWebApi.taggerCall.tags.some(t => t === "tag1") || 26 | !mocks.MockWebApi.taggerCall.tags.some(t => t === "tag2") || 27 | mocks.MockWebApi.taggerCall.tags.length !== 2) { 28 | console.log(mocks.MockWebApi.taggerCall); 29 | console.error("Tagging failed."); 30 | } 31 | else { 32 | console.log("Tagging successful!"); 33 | } 34 | }, 50); 35 | //# sourceMappingURL=test-multiTag-succeeds.js.map -------------------------------------------------------------------------------- /test/tagBuild/test-multiTag-succeeds.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import assert = require('assert'); 5 | import mocks = require('./mockWebApi'); 6 | 7 | let rootDir = path.join(__dirname, '../../Tasks', 'TagBuild'); 8 | let taskPath = path.join(rootDir, 'tagBuild.js'); 9 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 10 | 11 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 12 | 13 | // set variables 14 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 15 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 16 | process.env["BUILD_BUILDID"] = "1"; 17 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 18 | 19 | // set inputs 20 | tmr.setInput('tags', `tag1 21 | tag2`); 22 | tmr.setInput('type', 'Build'); 23 | 24 | tmr.run(); 25 | 26 | // need setTimeout because of async methods 27 | setTimeout(() => { 28 | if ("demo" !== mocks.MockWebApi.taggerCall.project || 29 | "Build" !== mocks.MockWebApi.taggerCall.callType || 30 | 1 !== mocks.MockWebApi.taggerCall.id || 31 | !mocks.MockWebApi.taggerCall.tags.some(t => t === "tag1") || 32 | !mocks.MockWebApi.taggerCall.tags.some(t => t === "tag2") || 33 | mocks.MockWebApi.taggerCall.tags.length !== 2) { 34 | console.log(mocks.MockWebApi.taggerCall); 35 | console.error("Tagging failed."); 36 | } else { 37 | console.log("Tagging successful!"); 38 | } 39 | }, 50); -------------------------------------------------------------------------------- /test/tagBuild/test-noauth-fails.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const mocks = require("./mockWebApi"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'TagBuild'); 7 | let taskPath = path.join(rootDir, 'tagBuild.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 10 | // set variables 11 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 12 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 13 | process.env["BUILD_BUILDID"] = "1"; 14 | // set inputs 15 | tmr.setInput('tags', `tag1 16 | tag2`); 17 | tmr.setInput('type', 'Build'); 18 | tmr.run(); 19 | //# sourceMappingURL=test-noauth-fails.js.map -------------------------------------------------------------------------------- /test/tagBuild/test-noauth-fails.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import assert = require('assert'); 5 | import mocks = require('./mockWebApi'); 6 | 7 | let rootDir = path.join(__dirname, '../../Tasks', 'TagBuild'); 8 | let taskPath = path.join(rootDir, 'tagBuild.js'); 9 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 10 | 11 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 12 | 13 | // set variables 14 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 15 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 16 | process.env["BUILD_BUILDID"] = "1"; 17 | 18 | // set inputs 19 | tmr.setInput('tags', `tag1 20 | tag2`); 21 | tmr.setInput('type', 'Build'); 22 | 23 | tmr.run(); -------------------------------------------------------------------------------- /test/tagBuild/test-release-noReleaseId-fails.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const mocks = require("./mockWebApi"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'TagBuild'); 7 | let taskPath = path.join(rootDir, 'tagBuild.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 10 | // set variables 11 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 12 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 13 | process.env["BUILD_BUILDID"] = "1"; 14 | // set inputs 15 | tmr.setInput('tags', `tag1 16 | tag2`); 17 | tmr.setInput('type', 'Release'); 18 | tmr.run(); 19 | //# sourceMappingURL=test-release-noReleaseId-fails.js.map -------------------------------------------------------------------------------- /test/tagBuild/test-release-noReleaseId-fails.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import assert = require('assert'); 5 | import mocks = require('./mockWebApi'); 6 | 7 | let rootDir = path.join(__dirname, '../../Tasks', 'TagBuild'); 8 | let taskPath = path.join(rootDir, 'tagBuild.js'); 9 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 10 | 11 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 12 | 13 | // set variables 14 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 15 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 16 | process.env["BUILD_BUILDID"] = "1"; 17 | 18 | // set inputs 19 | tmr.setInput('tags', `tag1 20 | tag2`); 21 | tmr.setInput('type', 'Release'); 22 | 23 | tmr.run(); -------------------------------------------------------------------------------- /test/tagBuild/test-singleTag-succeeds.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const mockWebApi_1 = require("./mockWebApi"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'TagBuild'); 7 | let taskPath = path.join(rootDir, 'tagBuild.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | tmr.registerMock('azure-devops-node-api/WebApi', mockWebApi_1.MockWebApi); 10 | // set variables 11 | let project = "demo"; 12 | let buildId = 1; 13 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 14 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 15 | process.env["SYSTEM_TEAMPROJECT"] = project; 16 | process.env["BUILD_BUILDID"] = buildId.toString(); 17 | // set inputs 18 | tmr.setInput('tags', 'tag1'); 19 | tmr.setInput('type', 'Build'); 20 | tmr.run(); 21 | // need setTimeout because of async methods 22 | setTimeout(() => { 23 | if ("demo" !== mockWebApi_1.MockWebApi.taggerCall.project || 24 | "Build" !== mockWebApi_1.MockWebApi.taggerCall.callType || 25 | 1 !== mockWebApi_1.MockWebApi.taggerCall.id || 26 | !mockWebApi_1.MockWebApi.taggerCall.tags.some(t => t === "tag1") || 27 | mockWebApi_1.MockWebApi.taggerCall.tags.length !== 1) { 28 | console.error("Tagging failed."); 29 | } 30 | else { 31 | console.log("Tagging successful!"); 32 | } 33 | }, 50); 34 | //# sourceMappingURL=test-singleTag-succeeds.js.map -------------------------------------------------------------------------------- /test/tagBuild/test-singleTag-succeeds.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import { MockWebApi } from './mockWebApi'; 5 | 6 | let rootDir = path.join(__dirname, '../../Tasks', 'TagBuild'); 7 | let taskPath = path.join(rootDir, 'tagBuild.js'); 8 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 9 | 10 | tmr.registerMock('azure-devops-node-api/WebApi', MockWebApi); 11 | 12 | // set variables 13 | let project = "demo"; 14 | let buildId = 1; 15 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 16 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 17 | process.env["SYSTEM_TEAMPROJECT"] = project; 18 | process.env["BUILD_BUILDID"] = buildId.toString(); 19 | 20 | // set inputs 21 | tmr.setInput('tags', 'tag1'); 22 | tmr.setInput('type', 'Build'); 23 | 24 | tmr.run(); 25 | 26 | // need setTimeout because of async methods 27 | setTimeout(() => { 28 | if ("demo" !== MockWebApi.taggerCall.project || 29 | "Build" !== MockWebApi.taggerCall.callType || 30 | 1 !== MockWebApi.taggerCall.id || 31 | !MockWebApi.taggerCall.tags.some(t => t === "tag1") || 32 | MockWebApi.taggerCall.tags.length !== 1) { 33 | console.error("Tagging failed."); 34 | } else { 35 | console.log("Tagging successful!"); 36 | } 37 | }, 50); -------------------------------------------------------------------------------- /test/tagBuild/test-tagBuildFromRelease-succeeds.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const mocks = require("./mockWebApi"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'TagBuild'); 7 | let taskPath = path.join(rootDir, 'tagBuild.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 10 | // set variables 11 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 12 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 13 | process.env["BUILD_BUILDID"] = "1"; 14 | process.env["RELEAS_RELEASEID"] = "22"; 15 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 16 | // set inputs 17 | tmr.setInput('tags', 'tag1'); 18 | tmr.setInput('type', 'Build'); 19 | tmr.run(); 20 | // need setTimeout because of async methods 21 | setTimeout(() => { 22 | if ("demo" !== mocks.MockWebApi.taggerCall.project || 23 | "Build" !== mocks.MockWebApi.taggerCall.callType || 24 | 1 !== mocks.MockWebApi.taggerCall.id || 25 | !mocks.MockWebApi.taggerCall.tags.some(t => t === "tag1") || 26 | mocks.MockWebApi.taggerCall.tags.length !== 1) { 27 | console.log(mocks.MockWebApi.taggerCall); 28 | console.error("Tagging failed."); 29 | } 30 | else { 31 | console.log("Tagging successful!"); 32 | } 33 | }, 100); 34 | //# sourceMappingURL=test-tagBuildFromRelease-succeeds.js.map -------------------------------------------------------------------------------- /test/tagBuild/test-tagBuildFromRelease-succeeds.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import assert = require('assert'); 5 | import mocks = require('./mockWebApi'); 6 | 7 | let rootDir = path.join(__dirname, '../../Tasks', 'TagBuild'); 8 | let taskPath = path.join(rootDir, 'tagBuild.js'); 9 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 10 | 11 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 12 | 13 | // set variables 14 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 15 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 16 | process.env["BUILD_BUILDID"] = "1"; 17 | process.env["RELEAS_RELEASEID"] = "22"; 18 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 19 | 20 | // set inputs 21 | tmr.setInput('tags', 'tag1'); 22 | tmr.setInput('type', 'Build'); 23 | 24 | tmr.run(); 25 | 26 | // need setTimeout because of async methods 27 | setTimeout(() => { 28 | if ("demo" !== mocks.MockWebApi.taggerCall.project || 29 | "Build" !== mocks.MockWebApi.taggerCall.callType || 30 | 1 !== mocks.MockWebApi.taggerCall.id || 31 | !mocks.MockWebApi.taggerCall.tags.some(t => t === "tag1") || 32 | mocks.MockWebApi.taggerCall.tags.length !== 1) { 33 | console.log(mocks.MockWebApi.taggerCall); 34 | console.error("Tagging failed."); 35 | } else { 36 | console.log("Tagging successful!"); 37 | } 38 | }, 100); -------------------------------------------------------------------------------- /test/tagBuild/test-tagBuildHandlesFailedCall.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const mocks = require("./mockErrorWebApi"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'TagBuild'); 7 | let taskPath = path.join(rootDir, 'tagBuild.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 10 | // set variables 11 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 12 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 13 | process.env["BUILD_BUILDID"] = "1"; 14 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 15 | // set inputs 16 | tmr.setInput('tags', 'tag1'); 17 | tmr.setInput('type', 'Build'); 18 | tmr.run(); 19 | //# sourceMappingURL=test-tagBuildHandlesFailedCall.js.map -------------------------------------------------------------------------------- /test/tagBuild/test-tagBuildHandlesFailedCall.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import assert = require('assert'); 5 | import mocks = require('./mockErrorWebApi'); 6 | 7 | let rootDir = path.join(__dirname, '../../Tasks', 'TagBuild'); 8 | let taskPath = path.join(rootDir, 'tagBuild.js'); 9 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 10 | 11 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 12 | 13 | // set variables 14 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 15 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 16 | process.env["BUILD_BUILDID"] = "1"; 17 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 18 | 19 | // set inputs 20 | tmr.setInput('tags', 'tag1'); 21 | tmr.setInput('type', 'Build'); 22 | 23 | tmr.run(); -------------------------------------------------------------------------------- /test/tagBuild/test-tagRelease-succeeds.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const mocks = require("./mockWebApi"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'TagBuild'); 7 | let taskPath = path.join(rootDir, 'tagBuild.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 10 | // set variables 11 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 12 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 13 | process.env["RELEASE_RELEASEID"] = "21"; 14 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 15 | // set inputs 16 | tmr.setInput('tags', 'tag1'); 17 | tmr.setInput('type', 'Release'); 18 | tmr.run(); 19 | // hack since testrunner returns void but tasks can be Promise 20 | setTimeout(t => { 21 | if ("demo" !== mocks.MockWebApi.taggerCall.project || 22 | "Release" !== mocks.MockWebApi.taggerCall.callType || 23 | 21 !== mocks.MockWebApi.taggerCall.id || 24 | !mocks.MockWebApi.taggerCall.tags.some(t => t === "tag1") || 25 | mocks.MockWebApi.taggerCall.tags.length !== 1) { 26 | console.log(mocks.MockWebApi.taggerCall); 27 | console.error("Tagging failed."); 28 | } 29 | else { 30 | console.log("Tagging successful!"); 31 | } 32 | }, 50); 33 | //# sourceMappingURL=test-tagRelease-succeeds.js.map -------------------------------------------------------------------------------- /test/tagBuild/test-tagRelease-succeeds.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import assert = require('assert'); 5 | import mocks = require('./mockWebApi'); 6 | 7 | let rootDir = path.join(__dirname, '../../Tasks', 'TagBuild'); 8 | let taskPath = path.join(rootDir, 'tagBuild.js'); 9 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 10 | 11 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 12 | 13 | // set variables 14 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 15 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 16 | process.env["RELEASE_RELEASEID"] = "21"; 17 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 18 | 19 | // set inputs 20 | tmr.setInput('tags', 'tag1'); 21 | tmr.setInput('type', 'Release'); 22 | 23 | tmr.run(); 24 | 25 | // hack since testrunner returns void but tasks can be Promise 26 | setTimeout(t => { 27 | if ("demo" !== mocks.MockWebApi.taggerCall.project || 28 | "Release" !== mocks.MockWebApi.taggerCall.callType || 29 | 21 !== mocks.MockWebApi.taggerCall.id || 30 | !mocks.MockWebApi.taggerCall.tags.some(t => t === "tag1") || 31 | mocks.MockWebApi.taggerCall.tags.length !== 1) { 32 | console.log(mocks.MockWebApi.taggerCall); 33 | console.error("Tagging failed."); 34 | } else { 35 | console.log("Tagging successful!"); 36 | } 37 | }, 50); -------------------------------------------------------------------------------- /test/tagBuild/test-tagReleaseHandlesFailedCall.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const mocks = require("./mockErrorWebApi"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'TagBuild'); 7 | let taskPath = path.join(rootDir, 'tagBuild.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 10 | // set variables 11 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 12 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 13 | process.env["RELEASE_RELEASEID"] = "21"; 14 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 15 | // set inputs 16 | tmr.setInput('tags', 'tag1'); 17 | tmr.setInput('type', 'Release'); 18 | tmr.run(); 19 | //# sourceMappingURL=test-tagReleaseHandlesFailedCall.js.map -------------------------------------------------------------------------------- /test/tagBuild/test-tagReleaseHandlesFailedCall.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import assert = require('assert'); 5 | import mocks = require('./mockErrorWebApi'); 6 | 7 | let rootDir = path.join(__dirname, '../../Tasks', 'TagBuild'); 8 | let taskPath = path.join(rootDir, 'tagBuild.js'); 9 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 10 | 11 | tmr.registerMock('azure-devops-node-api/WebApi', mocks.MockWebApi); 12 | 13 | // set variables 14 | process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "http://localhost:8080/tfs/defaultcollection"; 15 | process.env["SYSTEM_TEAMPROJECT"] = "demo"; 16 | process.env["RELEASE_RELEASEID"] = "21"; 17 | process.env["SYSTEM_ACCESSTOKEN"] = "faketoken"; 18 | 19 | // set inputs 20 | tmr.setInput('tags', 'tag1'); 21 | tmr.setInput('type', 'Release'); 22 | 23 | tmr.run(); -------------------------------------------------------------------------------- /test/tokenizer/test-all.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const fs = require("fs"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'Tokenizer'); 7 | let taskPath = path.join(rootDir, 'tokenizer.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // set up a tmp file for the test 10 | var workingFolder = path.join(__dirname, "working"); 11 | if (!fs.existsSync(workingFolder)) { 12 | fs.mkdirSync(workingFolder); 13 | } 14 | var tmpFile = path.join(workingFolder, "appsettings.json"); 15 | // provide answers for task mock 16 | let a = { 17 | "checkPath": { 18 | "working": true 19 | }, 20 | "findMatch": { 21 | "appsettings.json": [tmpFile] 22 | } 23 | }; 24 | tmr.setAnswers(a); 25 | fs.writeFile(tmpFile, ` 26 | { 27 | "ConnectionStrings": { 28 | "DefaultConnection": "Server=(localdb)\\\\mssqllocaldb;Database=aspnet-WebApplication1-26e8893e-d7c0-4fc6-8aab-29b59971d622;Trusted_Connection=True;MultipleActiveResultSets=true" 29 | }, 30 | "Tricky": { 31 | "Tricky": "Tricky", 32 | "Tricky1": { 33 | "Tricky2": "Tricky" 34 | } 35 | }, 36 | "Logging": { 37 | "IncludeScopes": false, 38 | "LogLevel": { 39 | "Default": "Debug", 40 | "System": "Information", 41 | "Microsoft": "Information" 42 | } 43 | } 44 | } 45 | `, (err) => { 46 | // set inputs 47 | tmr.setInput('sourcePath', "working"); 48 | tmr.setInput('filePattern', 'appsettings.json'); 49 | tmr.setInput('tokenizeType', 'Json'); 50 | tmr.setInput('includes', ''); 51 | tmr.setInput('excludes', ''); 52 | tmr.setInput('nullBehavior', 'warning'); 53 | tmr.run(); 54 | // validate the replacement 55 | let actual = fs.readFileSync(tmpFile).toString(); 56 | var expected = `{ 57 | "ConnectionStrings": { 58 | "DefaultConnection": "__ConnectionStrings.DefaultConnection__" 59 | }, 60 | "Tricky": { 61 | "Tricky": "__Tricky.Tricky__", 62 | "Tricky1": { 63 | "Tricky2": "__Tricky.Tricky1.Tricky2__" 64 | } 65 | }, 66 | "Logging": { 67 | "IncludeScopes": "__Logging.IncludeScopes__", 68 | "LogLevel": { 69 | "Default": "__Logging.LogLevel.Default__", 70 | "System": "__Logging.LogLevel.System__", 71 | "Microsoft": "__Logging.LogLevel.Microsoft__" 72 | } 73 | } 74 | }`; 75 | if (actual.trim() !== expected.trim()) { 76 | console.log(actual); 77 | console.error("Tokenization failed."); 78 | } 79 | else { 80 | console.log("Tokenization succeeded!"); 81 | } 82 | }); 83 | //# sourceMappingURL=test-all.js.map -------------------------------------------------------------------------------- /test/tokenizer/test-all.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import fs = require('fs'); 5 | 6 | let rootDir = path.join(__dirname, '../../Tasks', 'Tokenizer'); 7 | let taskPath = path.join(rootDir, 'tokenizer.js'); 8 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 9 | 10 | // set up a tmp file for the test 11 | var workingFolder = path.join(__dirname, "working"); 12 | if (!fs.existsSync(workingFolder)) { 13 | fs.mkdirSync(workingFolder); 14 | } 15 | var tmpFile = path.join(workingFolder, "appsettings.json"); 16 | 17 | // provide answers for task mock 18 | let a: ma.TaskLibAnswers = { 19 | "checkPath": { 20 | "working": true 21 | }, 22 | "findMatch": { 23 | "appsettings.json" : [ tmpFile ] 24 | } 25 | }; 26 | tmr.setAnswers(a); 27 | 28 | fs.writeFile(tmpFile, ` 29 | { 30 | "ConnectionStrings": { 31 | "DefaultConnection": "Server=(localdb)\\\\mssqllocaldb;Database=aspnet-WebApplication1-26e8893e-d7c0-4fc6-8aab-29b59971d622;Trusted_Connection=True;MultipleActiveResultSets=true" 32 | }, 33 | "Tricky": { 34 | "Tricky": "Tricky", 35 | "Tricky1": { 36 | "Tricky2": "Tricky" 37 | } 38 | }, 39 | "Logging": { 40 | "IncludeScopes": false, 41 | "LogLevel": { 42 | "Default": "Debug", 43 | "System": "Information", 44 | "Microsoft": "Information" 45 | } 46 | } 47 | } 48 | `, (err) => { 49 | 50 | // set inputs 51 | tmr.setInput('sourcePath', "working"); 52 | tmr.setInput('filePattern', 'appsettings.json'); 53 | tmr.setInput('tokenizeType', 'Json'); 54 | tmr.setInput('includes', ''); 55 | tmr.setInput('excludes', ''); 56 | tmr.setInput('nullBehavior', 'warning'); 57 | 58 | tmr.run(); 59 | 60 | // validate the replacement 61 | let actual = fs.readFileSync(tmpFile).toString(); 62 | var expected = `{ 63 | "ConnectionStrings": { 64 | "DefaultConnection": "__ConnectionStrings.DefaultConnection__" 65 | }, 66 | "Tricky": { 67 | "Tricky": "__Tricky.Tricky__", 68 | "Tricky1": { 69 | "Tricky2": "__Tricky.Tricky1.Tricky2__" 70 | } 71 | }, 72 | "Logging": { 73 | "IncludeScopes": "__Logging.IncludeScopes__", 74 | "LogLevel": { 75 | "Default": "__Logging.LogLevel.Default__", 76 | "System": "__Logging.LogLevel.System__", 77 | "Microsoft": "__Logging.LogLevel.Microsoft__" 78 | } 79 | } 80 | }`; 81 | 82 | if (actual.trim() !== expected.trim()) { 83 | console.log(actual); 84 | console.error("Tokenization failed."); 85 | } else { 86 | console.log("Tokenization succeeded!") 87 | } 88 | }); -------------------------------------------------------------------------------- /test/tokenizer/test-defaults.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const fs = require("fs"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'Tokenizer'); 7 | let taskPath = path.join(rootDir, 'tokenizer.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // set up a tmp file for the test 10 | var workingFolder = path.join(__dirname, "working"); 11 | if (!fs.existsSync(workingFolder)) { 12 | fs.mkdirSync(workingFolder); 13 | } 14 | var tmpFile = path.join(workingFolder, "appsettings.json"); 15 | // provide answers for task mock 16 | let a = { 17 | "checkPath": { 18 | "working": true 19 | }, 20 | "findMatch": { 21 | "appsettings.json": [tmpFile] 22 | } 23 | }; 24 | tmr.setAnswers(a); 25 | fs.writeFile(tmpFile, ` 26 | { 27 | "ConnectionStrings": { 28 | "DefaultConnection": "Server=(localdb)\\\\mssqllocaldb;Database=aspnet-WebApplication1-26e8893e-d7c0-4fc6-8aab-29b59971d622;Trusted_Connection=True;MultipleActiveResultSets=true" 29 | }, 30 | "Tricky": { 31 | "Tricky": "Tricky", 32 | "Tricky1": { 33 | "Tricky2": "Tricky" 34 | } 35 | }, 36 | "Logging": { 37 | "IncludeScopes": false, 38 | "LogLevel": { 39 | "Default": "Debug", 40 | "System": "Information", 41 | "Microsoft": "Information" 42 | } 43 | } 44 | } 45 | `, (err) => { 46 | // set inputs 47 | tmr.setInput('sourcePath', "working"); 48 | tmr.setInput('filePattern', 'appsettings.json'); 49 | tmr.setInput('tokenizeType', 'Json'); 50 | tmr.setInput('includes', 'ConnectionStrings.DefaultConnection,Logging.LogLevel.Default'); 51 | tmr.setInput('excludes', ''); 52 | tmr.setInput('nullBehavior', 'warning'); 53 | tmr.run(); 54 | // validate the replacement 55 | let actual = fs.readFileSync(tmpFile).toString(); 56 | var expected = `{ 57 | "ConnectionStrings": { 58 | "DefaultConnection": "__ConnectionStrings.DefaultConnection__" 59 | }, 60 | "Tricky": { 61 | "Tricky": "Tricky", 62 | "Tricky1": { 63 | "Tricky2": "Tricky" 64 | } 65 | }, 66 | "Logging": { 67 | "IncludeScopes": false, 68 | "LogLevel": { 69 | "Default": "__Logging.LogLevel.Default__", 70 | "System": "Information", 71 | "Microsoft": "Information" 72 | } 73 | } 74 | }`; 75 | if (actual.trim() !== expected.trim()) { 76 | console.log(actual); 77 | console.error("Tokenization failed."); 78 | } 79 | else { 80 | console.log("Tokenization succeeded!"); 81 | } 82 | }); 83 | //# sourceMappingURL=test-defaults.js.map -------------------------------------------------------------------------------- /test/tokenizer/test-defaults.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import fs = require('fs'); 5 | 6 | let rootDir = path.join(__dirname, '../../Tasks', 'Tokenizer'); 7 | let taskPath = path.join(rootDir, 'tokenizer.js'); 8 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 9 | 10 | // set up a tmp file for the test 11 | var workingFolder = path.join(__dirname, "working"); 12 | if (!fs.existsSync(workingFolder)) { 13 | fs.mkdirSync(workingFolder); 14 | } 15 | var tmpFile = path.join(workingFolder, "appsettings.json"); 16 | 17 | // provide answers for task mock 18 | let a: ma.TaskLibAnswers = { 19 | "checkPath": { 20 | "working": true 21 | }, 22 | "findMatch": { 23 | "appsettings.json" : [ tmpFile ] 24 | } 25 | }; 26 | tmr.setAnswers(a); 27 | 28 | fs.writeFile(tmpFile, ` 29 | { 30 | "ConnectionStrings": { 31 | "DefaultConnection": "Server=(localdb)\\\\mssqllocaldb;Database=aspnet-WebApplication1-26e8893e-d7c0-4fc6-8aab-29b59971d622;Trusted_Connection=True;MultipleActiveResultSets=true" 32 | }, 33 | "Tricky": { 34 | "Tricky": "Tricky", 35 | "Tricky1": { 36 | "Tricky2": "Tricky" 37 | } 38 | }, 39 | "Logging": { 40 | "IncludeScopes": false, 41 | "LogLevel": { 42 | "Default": "Debug", 43 | "System": "Information", 44 | "Microsoft": "Information" 45 | } 46 | } 47 | } 48 | `, (err) => { 49 | 50 | // set inputs 51 | tmr.setInput('sourcePath', "working"); 52 | tmr.setInput('filePattern', 'appsettings.json'); 53 | tmr.setInput('tokenizeType', 'Json'); 54 | tmr.setInput('includes', 'ConnectionStrings.DefaultConnection,Logging.LogLevel.Default'); 55 | tmr.setInput('excludes', ''); 56 | tmr.setInput('nullBehavior', 'warning'); 57 | 58 | tmr.run(); 59 | 60 | // validate the replacement 61 | let actual = fs.readFileSync(tmpFile).toString(); 62 | var expected = `{ 63 | "ConnectionStrings": { 64 | "DefaultConnection": "__ConnectionStrings.DefaultConnection__" 65 | }, 66 | "Tricky": { 67 | "Tricky": "Tricky", 68 | "Tricky1": { 69 | "Tricky2": "Tricky" 70 | } 71 | }, 72 | "Logging": { 73 | "IncludeScopes": false, 74 | "LogLevel": { 75 | "Default": "__Logging.LogLevel.Default__", 76 | "System": "Information", 77 | "Microsoft": "Information" 78 | } 79 | } 80 | }`; 81 | 82 | if (actual.trim() !== expected.trim()) { 83 | console.log(actual); 84 | console.error("Tokenization failed."); 85 | } else { 86 | console.log("Tokenization succeeded!") 87 | } 88 | }); -------------------------------------------------------------------------------- /test/tokenizer/test-dotTokens.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const fs = require("fs"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'Tokenizer'); 7 | let taskPath = path.join(rootDir, 'replaceTokens.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // set up a tmp file for the test 10 | var workingFolder = path.join(__dirname, "working"); 11 | if (!fs.existsSync(workingFolder)) { 12 | fs.mkdirSync(workingFolder); 13 | } 14 | var tmpFile = path.join(workingFolder, "appsettings.json"); 15 | // provide answers for task mock 16 | let a = { 17 | "checkPath": { 18 | "working": true 19 | }, 20 | "findMatch": { 21 | "appsettings.json": [tmpFile] 22 | } 23 | }; 24 | tmr.setAnswers(a); 25 | fs.writeFile(tmpFile, ` 26 | { 27 | "ConnectionStrings": { 28 | "DefaultConnection": "__ConnectionStrings.DefaultConnection__" 29 | }, 30 | "Tricky": { 31 | "Gollum": "__Tricky.Gollum__", 32 | "Hobbit": "__Tricky.Hobbit__" 33 | }, 34 | "Logging": { 35 | "IncludeScopes": false, 36 | "LogLevel": { 37 | "Default": "Debug", 38 | "System": "Information", 39 | "Microsoft": "Information" 40 | } 41 | } 42 | } 43 | `, (err) => { 44 | // set inputs 45 | tmr.setInput('sourcePath', "working"); 46 | tmr.setInput('filePattern', 'appsettings.json'); 47 | tmr.setInput('tokenRegex', '__(\\w+[\\.\\w+]*)__'); 48 | tmr.setInput('nullBehavior', 'warning'); 49 | // set variables 50 | process.env["CONNECTIONSTRINGS_DEFAULTCONNECTION"] = "testing"; 51 | process.env["TRICKY_GOLLUM"] = "Gollum2"; 52 | process.env["TRICKY_HOBBIT"] = "Sam"; 53 | tmr.run(); 54 | // validate the replacement 55 | let actual = fs.readFileSync('working/appsettings.json').toString(); 56 | var expected = ` 57 | { 58 | "ConnectionStrings": { 59 | "DefaultConnection": "testing" 60 | }, 61 | "Tricky": { 62 | "Gollum": "Gollum2", 63 | "Hobbit": "Sam" 64 | }, 65 | "Logging": { 66 | "IncludeScopes": false, 67 | "LogLevel": { 68 | "Default": "Debug", 69 | "System": "Information", 70 | "Microsoft": "Information" 71 | } 72 | } 73 | } 74 | `; 75 | if (actual.trim() !== expected.trim()) { 76 | console.log(actual); 77 | console.error("Replacement failed."); 78 | } 79 | else { 80 | console.log("Replacement succeeded!"); 81 | } 82 | }); 83 | //# sourceMappingURL=test-dotTokens.js.map -------------------------------------------------------------------------------- /test/tokenizer/test-dotTokens.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import fs = require('fs'); 5 | 6 | let rootDir = path.join(__dirname, '../../Tasks', 'Tokenizer'); 7 | let taskPath = path.join(rootDir, 'replaceTokens.js'); 8 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 9 | 10 | // set up a tmp file for the test 11 | var workingFolder = path.join(__dirname, "working"); 12 | if (!fs.existsSync(workingFolder)) { 13 | fs.mkdirSync(workingFolder); 14 | } 15 | var tmpFile = path.join(workingFolder, "appsettings.json"); 16 | 17 | // provide answers for task mock 18 | let a: ma.TaskLibAnswers = { 19 | "checkPath": { 20 | "working": true 21 | }, 22 | "findMatch": { 23 | "appsettings.json" : [ tmpFile ] 24 | } 25 | }; 26 | tmr.setAnswers(a); 27 | 28 | fs.writeFile(tmpFile, ` 29 | { 30 | "ConnectionStrings": { 31 | "DefaultConnection": "__ConnectionStrings.DefaultConnection__" 32 | }, 33 | "Tricky": { 34 | "Gollum": "__Tricky.Gollum__", 35 | "Hobbit": "__Tricky.Hobbit__" 36 | }, 37 | "Logging": { 38 | "IncludeScopes": false, 39 | "LogLevel": { 40 | "Default": "Debug", 41 | "System": "Information", 42 | "Microsoft": "Information" 43 | } 44 | } 45 | } 46 | `, 47 | (err) => { 48 | 49 | // set inputs 50 | tmr.setInput('sourcePath', "working"); 51 | tmr.setInput('filePattern', 'appsettings.json'); 52 | tmr.setInput('tokenRegex', '__(\\w+[\\.\\w+]*)__'); 53 | tmr.setInput('nullBehavior', 'warning'); 54 | 55 | // set variables 56 | process.env["CONNECTIONSTRINGS_DEFAULTCONNECTION"] = "testing"; 57 | process.env["TRICKY_GOLLUM"] = "Gollum2"; 58 | process.env["TRICKY_HOBBIT"] = "Sam"; 59 | 60 | tmr.run(); 61 | 62 | // validate the replacement 63 | let actual = fs.readFileSync('working/appsettings.json').toString(); 64 | 65 | var expected = ` 66 | { 67 | "ConnectionStrings": { 68 | "DefaultConnection": "testing" 69 | }, 70 | "Tricky": { 71 | "Gollum": "Gollum2", 72 | "Hobbit": "Sam" 73 | }, 74 | "Logging": { 75 | "IncludeScopes": false, 76 | "LogLevel": { 77 | "Default": "Debug", 78 | "System": "Information", 79 | "Microsoft": "Information" 80 | } 81 | } 82 | } 83 | `; 84 | 85 | if (actual.trim() !== expected.trim()) { 86 | console.log(actual); 87 | console.error("Replacement failed."); 88 | } else { 89 | console.log("Replacement succeeded!") 90 | } 91 | }); -------------------------------------------------------------------------------- /test/tokenizer/test-exclude.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const fs = require("fs"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'Tokenizer'); 7 | let taskPath = path.join(rootDir, 'tokenizer.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // set up a tmp file for the test 10 | var workingFolder = path.join(__dirname, "working"); 11 | if (!fs.existsSync(workingFolder)) { 12 | fs.mkdirSync(workingFolder); 13 | } 14 | var tmpFile = path.join(workingFolder, "appsettings.json"); 15 | // provide answers for task mock 16 | let a = { 17 | "checkPath": { 18 | "working": true 19 | }, 20 | "findMatch": { 21 | "appsettings.json": [tmpFile] 22 | } 23 | }; 24 | tmr.setAnswers(a); 25 | // mock the fs 26 | fs.writeFile(tmpFile, ` 27 | { 28 | "ConnectionStrings": { 29 | "DefaultConnection": "Server=(localdb)\\\\mssqllocaldb;Database=aspnet-WebApplication1-26e8893e-d7c0-4fc6-8aab-29b59971d622;Trusted_Connection=True;MultipleActiveResultSets=true" 30 | }, 31 | "Tricky": { 32 | "Tricky": "Tricky", 33 | "Tricky1": { 34 | "Tricky2": "Tricky" 35 | } 36 | }, 37 | "Logging": { 38 | "IncludeScopes": false, 39 | "LogLevel": { 40 | "Default": "Debug" 41 | } 42 | } 43 | } 44 | `, (err) => { 45 | // set inputs 46 | tmr.setInput('sourcePath', "working"); 47 | tmr.setInput('filePattern', 'appsettings.json'); 48 | tmr.setInput('tokenizeType', 'Json'); 49 | tmr.setInput('includes', ''); 50 | tmr.setInput('excludes', 'Logging.IncludeScopes'); 51 | tmr.setInput('nullBehavior', 'warning'); 52 | tmr.run(); 53 | // validate the replacement 54 | let actual = fs.readFileSync(tmpFile).toString(); 55 | var expected = `{ 56 | "ConnectionStrings": { 57 | "DefaultConnection": "__ConnectionStrings.DefaultConnection__" 58 | }, 59 | "Tricky": { 60 | "Tricky": "__Tricky.Tricky__", 61 | "Tricky1": { 62 | "Tricky2": "__Tricky.Tricky1.Tricky2__" 63 | } 64 | }, 65 | "Logging": { 66 | "IncludeScopes": false, 67 | "LogLevel": { 68 | "Default": "__Logging.LogLevel.Default__" 69 | } 70 | } 71 | }`; 72 | if (actual.trim() !== expected.trim()) { 73 | console.log(actual); 74 | console.error("Tokenization failed."); 75 | } 76 | else { 77 | console.log("Tokenization succeeded!"); 78 | } 79 | }); 80 | //# sourceMappingURL=test-exclude.js.map -------------------------------------------------------------------------------- /test/tokenizer/test-exclude.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import fs = require('fs'); 5 | 6 | let rootDir = path.join(__dirname, '../../Tasks', 'Tokenizer'); 7 | let taskPath = path.join(rootDir, 'tokenizer.js'); 8 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 9 | 10 | // set up a tmp file for the test 11 | var workingFolder = path.join(__dirname, "working"); 12 | if (!fs.existsSync(workingFolder)) { 13 | fs.mkdirSync(workingFolder); 14 | } 15 | var tmpFile = path.join(workingFolder, "appsettings.json"); 16 | 17 | // provide answers for task mock 18 | let a: ma.TaskLibAnswers = { 19 | "checkPath": { 20 | "working": true 21 | }, 22 | "findMatch": { 23 | "appsettings.json" : [ tmpFile ] 24 | } 25 | }; 26 | tmr.setAnswers(a); 27 | 28 | // mock the fs 29 | fs.writeFile(tmpFile, ` 30 | { 31 | "ConnectionStrings": { 32 | "DefaultConnection": "Server=(localdb)\\\\mssqllocaldb;Database=aspnet-WebApplication1-26e8893e-d7c0-4fc6-8aab-29b59971d622;Trusted_Connection=True;MultipleActiveResultSets=true" 33 | }, 34 | "Tricky": { 35 | "Tricky": "Tricky", 36 | "Tricky1": { 37 | "Tricky2": "Tricky" 38 | } 39 | }, 40 | "Logging": { 41 | "IncludeScopes": false, 42 | "LogLevel": { 43 | "Default": "Debug" 44 | } 45 | } 46 | } 47 | `, (err) => { 48 | 49 | // set inputs 50 | tmr.setInput('sourcePath', "working"); 51 | tmr.setInput('filePattern', 'appsettings.json'); 52 | tmr.setInput('tokenizeType', 'Json'); 53 | tmr.setInput('includes', ''); 54 | tmr.setInput('excludes', 'Logging.IncludeScopes'); 55 | tmr.setInput('nullBehavior', 'warning'); 56 | 57 | tmr.run(); 58 | 59 | // validate the replacement 60 | let actual = fs.readFileSync(tmpFile).toString(); 61 | var expected = `{ 62 | "ConnectionStrings": { 63 | "DefaultConnection": "__ConnectionStrings.DefaultConnection__" 64 | }, 65 | "Tricky": { 66 | "Tricky": "__Tricky.Tricky__", 67 | "Tricky1": { 68 | "Tricky2": "__Tricky.Tricky1.Tricky2__" 69 | } 70 | }, 71 | "Logging": { 72 | "IncludeScopes": false, 73 | "LogLevel": { 74 | "Default": "__Logging.LogLevel.Default__" 75 | } 76 | } 77 | }`; 78 | 79 | if (actual.trim() !== expected.trim()) { 80 | console.log(actual); 81 | console.error("Tokenization failed."); 82 | } else { 83 | console.log("Tokenization succeeded!") 84 | } 85 | }); -------------------------------------------------------------------------------- /test/tokenizer/test-failIfBothIncAndExcSpecified.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | let rootDir = path.join(__dirname, '../../Tasks', 'Tokenizer'); 6 | let taskPath = path.join(rootDir, 'tokenizer.js'); 7 | let tmr = new tmrm.TaskMockRunner(taskPath); 8 | // set up a tmp file for the test 9 | var workingFolder = path.join(__dirname, "working"); 10 | var tmpFile = path.join(workingFolder, "appsettings.json"); 11 | // provide answers for task mock 12 | let a = { 13 | "checkPath": { 14 | "working": true 15 | }, 16 | "findMatch": { 17 | "appsettings.json": [tmpFile] 18 | } 19 | }; 20 | tmr.setAnswers(a); 21 | // set inputs 22 | tmr.setInput('sourcePath', "working"); 23 | tmr.setInput('filePattern', 'appsettings.json'); 24 | tmr.setInput('tokenizeType', 'Json'); 25 | tmr.setInput('includes', 'blah'); 26 | tmr.setInput('excludes', 'foo'); 27 | tmr.setInput('nullBehavior', 'warning'); 28 | tmr.run(); 29 | // expect failures 30 | //# sourceMappingURL=test-failIfBothIncAndExcSpecified.js.map -------------------------------------------------------------------------------- /test/tokenizer/test-failIfBothIncAndExcSpecified.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | 5 | let rootDir = path.join(__dirname, '../../Tasks', 'Tokenizer'); 6 | let taskPath = path.join(rootDir, 'tokenizer.js'); 7 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 8 | 9 | // set up a tmp file for the test 10 | var workingFolder = path.join(__dirname, "working"); 11 | var tmpFile = path.join(workingFolder, "appsettings.json"); 12 | 13 | // provide answers for task mock 14 | let a: ma.TaskLibAnswers = { 15 | "checkPath": { 16 | "working": true 17 | }, 18 | "findMatch": { 19 | "appsettings.json" : [ tmpFile ] 20 | } 21 | }; 22 | tmr.setAnswers(a); 23 | 24 | // set inputs 25 | tmr.setInput('sourcePath', "working"); 26 | tmr.setInput('filePattern', 'appsettings.json'); 27 | tmr.setInput('tokenizeType', 'Json'); 28 | tmr.setInput('includes', 'blah'); 29 | tmr.setInput('excludes', 'foo'); 30 | tmr.setInput('nullBehavior', 'warning'); 31 | 32 | tmr.run(); 33 | 34 | // expect failures -------------------------------------------------------------------------------- /test/tokenizer/test-failsWhenNullBehaviorIsError.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const fs = require("fs"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'Tokenizer'); 7 | let taskPath = path.join(rootDir, 'tokenizer.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // set up a tmp file for the test 10 | var workingFolder = path.join(__dirname, "working"); 11 | if (!fs.existsSync(workingFolder)) { 12 | fs.mkdirSync(workingFolder); 13 | } 14 | var tmpFile = path.join(workingFolder, "appsettings.json"); 15 | // provide answers for task mock 16 | let a = { 17 | "checkPath": { 18 | "working": true 19 | }, 20 | "findMatch": { 21 | "appsettings.json": [tmpFile] 22 | } 23 | }; 24 | tmr.setAnswers(a); 25 | fs.writeFile(tmpFile, ` 26 | { 27 | "ConnectionStrings": { 28 | "DefaultConnection": "Server=(localdb)\\\\mssqllocaldb;Database=aspnet-WebApplication1-26e8893e-d7c0-4fc6-8aab-29b59971d622;Trusted_Connection=True;MultipleActiveResultSets=true" 29 | }, 30 | "Tricky": { 31 | "Tricky": null, 32 | "Tricky1": { 33 | "Tricky2": "Tricky" 34 | } 35 | }, 36 | "Logging": { 37 | "IncludeScopes": false, 38 | "LogLevel": { 39 | "Default": "Debug", 40 | "System": "Information", 41 | "Microsoft": "Information" 42 | } 43 | } 44 | } 45 | `, (err) => { 46 | // set inputs 47 | tmr.setInput('sourcePath', "working"); 48 | tmr.setInput('filePattern', 'appsettings.json'); 49 | tmr.setInput('tokenizeType', 'Json'); 50 | tmr.setInput('includes', 'ConnectionStrings.DefaultConnection,Logging.LogLevel.Default'); 51 | tmr.setInput('excludes', ''); 52 | tmr.setInput('nullBehavior', 'error'); 53 | tmr.run(); 54 | }); 55 | //# sourceMappingURL=test-failsWhenNullBehaviorIsError.js.map -------------------------------------------------------------------------------- /test/tokenizer/test-failsWhenNullBehaviorIsError.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import fs = require('fs'); 5 | 6 | let rootDir = path.join(__dirname, '../../Tasks', 'Tokenizer'); 7 | let taskPath = path.join(rootDir, 'tokenizer.js'); 8 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 9 | 10 | // set up a tmp file for the test 11 | var workingFolder = path.join(__dirname, "working"); 12 | if (!fs.existsSync(workingFolder)) { 13 | fs.mkdirSync(workingFolder); 14 | } 15 | var tmpFile = path.join(workingFolder, "appsettings.json"); 16 | 17 | // provide answers for task mock 18 | let a: ma.TaskLibAnswers = { 19 | "checkPath": { 20 | "working": true 21 | }, 22 | "findMatch": { 23 | "appsettings.json" : [ tmpFile ] 24 | } 25 | }; 26 | tmr.setAnswers(a); 27 | 28 | fs.writeFile(tmpFile, ` 29 | { 30 | "ConnectionStrings": { 31 | "DefaultConnection": "Server=(localdb)\\\\mssqllocaldb;Database=aspnet-WebApplication1-26e8893e-d7c0-4fc6-8aab-29b59971d622;Trusted_Connection=True;MultipleActiveResultSets=true" 32 | }, 33 | "Tricky": { 34 | "Tricky": null, 35 | "Tricky1": { 36 | "Tricky2": "Tricky" 37 | } 38 | }, 39 | "Logging": { 40 | "IncludeScopes": false, 41 | "LogLevel": { 42 | "Default": "Debug", 43 | "System": "Information", 44 | "Microsoft": "Information" 45 | } 46 | } 47 | } 48 | `, (err) => { 49 | 50 | // set inputs 51 | tmr.setInput('sourcePath', "working"); 52 | tmr.setInput('filePattern', 'appsettings.json'); 53 | tmr.setInput('tokenizeType', 'Json'); 54 | tmr.setInput('includes', 'ConnectionStrings.DefaultConnection,Logging.LogLevel.Default'); 55 | tmr.setInput('excludes', ''); 56 | tmr.setInput('nullBehavior', 'error'); 57 | 58 | tmr.run(); 59 | }); -------------------------------------------------------------------------------- /test/tokenizer/test-trailingSlash.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const fs = require("fs"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'Tokenizer'); 7 | let taskPath = path.join(rootDir, 'tokenizer.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // set up a tmp file for the test 10 | var workingFolder = path.join(__dirname, "working"); 11 | if (!fs.existsSync(workingFolder)) { 12 | fs.mkdirSync(workingFolder); 13 | } 14 | var tmpFile = path.join(workingFolder, "appsettings.json"); 15 | // provide answers for task mock 16 | let a = { 17 | "checkPath": { 18 | "working": true 19 | }, 20 | "findMatch": { 21 | "appsettings.json": [tmpFile] 22 | } 23 | }; 24 | tmr.setAnswers(a); 25 | fs.writeFile(tmpFile, ` 26 | { 27 | "ConnectionStrings": { 28 | "DefaultConnection": "Server=(localdb)\\\\mssqllocaldb;Database=aspnet-WebApplication1-26e8893e-d7c0-4fc6-8aab-29b59971d622;Trusted_Connection=True;MultipleActiveResultSets=true" 29 | }, 30 | "Tricky": { 31 | "Tricky": "Tricky", 32 | "Tricky1": { 33 | "Tricky2": "Tricky" 34 | } 35 | }, 36 | "Logging": { 37 | "IncludeScopes": false, 38 | "LogLevel": { 39 | "Default": "Debug", 40 | "System": "Information", 41 | "Microsoft": "Information" 42 | } 43 | } 44 | } 45 | `, (err) => { 46 | // set inputs 47 | tmr.setInput('sourcePath', "working/"); 48 | tmr.setInput('filePattern', 'appsettings.json'); 49 | tmr.setInput('tokenizeType', 'Json'); 50 | tmr.setInput('includes', 'ConnectionStrings.DefaultConnection,Logging.LogLevel.Default'); 51 | tmr.setInput('excludes', ''); 52 | tmr.setInput('nullBehavior', 'warning'); 53 | tmr.run(); 54 | // validate the replacement 55 | let actual = fs.readFileSync(tmpFile).toString(); 56 | var expected = `{ 57 | "ConnectionStrings": { 58 | "DefaultConnection": "__ConnectionStrings.DefaultConnection__" 59 | }, 60 | "Tricky": { 61 | "Tricky": "Tricky", 62 | "Tricky1": { 63 | "Tricky2": "Tricky" 64 | } 65 | }, 66 | "Logging": { 67 | "IncludeScopes": false, 68 | "LogLevel": { 69 | "Default": "__Logging.LogLevel.Default__", 70 | "System": "Information", 71 | "Microsoft": "Information" 72 | } 73 | } 74 | }`; 75 | if (actual.trim() !== expected.trim()) { 76 | console.log(actual); 77 | console.error("Tokenization failed."); 78 | } 79 | else { 80 | console.log("Tokenization succeeded!"); 81 | } 82 | }); 83 | //# sourceMappingURL=test-trailingSlash.js.map -------------------------------------------------------------------------------- /test/tokenizer/test-trailingSlash.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import fs = require('fs'); 5 | 6 | let rootDir = path.join(__dirname, '../../Tasks', 'Tokenizer'); 7 | let taskPath = path.join(rootDir, 'tokenizer.js'); 8 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 9 | 10 | // set up a tmp file for the test 11 | var workingFolder = path.join(__dirname, "working"); 12 | if (!fs.existsSync(workingFolder)) { 13 | fs.mkdirSync(workingFolder); 14 | } 15 | var tmpFile = path.join(workingFolder, "appsettings.json"); 16 | 17 | // provide answers for task mock 18 | let a: ma.TaskLibAnswers = { 19 | "checkPath": { 20 | "working": true 21 | }, 22 | "findMatch": { 23 | "appsettings.json" : [ tmpFile ] 24 | } 25 | }; 26 | tmr.setAnswers(a); 27 | 28 | fs.writeFile(tmpFile, ` 29 | { 30 | "ConnectionStrings": { 31 | "DefaultConnection": "Server=(localdb)\\\\mssqllocaldb;Database=aspnet-WebApplication1-26e8893e-d7c0-4fc6-8aab-29b59971d622;Trusted_Connection=True;MultipleActiveResultSets=true" 32 | }, 33 | "Tricky": { 34 | "Tricky": "Tricky", 35 | "Tricky1": { 36 | "Tricky2": "Tricky" 37 | } 38 | }, 39 | "Logging": { 40 | "IncludeScopes": false, 41 | "LogLevel": { 42 | "Default": "Debug", 43 | "System": "Information", 44 | "Microsoft": "Information" 45 | } 46 | } 47 | } 48 | `, (err) => { 49 | 50 | // set inputs 51 | tmr.setInput('sourcePath', "working/"); 52 | tmr.setInput('filePattern', 'appsettings.json'); 53 | tmr.setInput('tokenizeType', 'Json'); 54 | tmr.setInput('includes', 'ConnectionStrings.DefaultConnection,Logging.LogLevel.Default'); 55 | tmr.setInput('excludes', ''); 56 | tmr.setInput('nullBehavior', 'warning'); 57 | 58 | tmr.run(); 59 | 60 | // validate the replacement 61 | let actual = fs.readFileSync(tmpFile).toString(); 62 | var expected = `{ 63 | "ConnectionStrings": { 64 | "DefaultConnection": "__ConnectionStrings.DefaultConnection__" 65 | }, 66 | "Tricky": { 67 | "Tricky": "Tricky", 68 | "Tricky1": { 69 | "Tricky2": "Tricky" 70 | } 71 | }, 72 | "Logging": { 73 | "IncludeScopes": false, 74 | "LogLevel": { 75 | "Default": "__Logging.LogLevel.Default__", 76 | "System": "Information", 77 | "Microsoft": "Information" 78 | } 79 | } 80 | }`; 81 | 82 | if (actual.trim() !== expected.trim()) { 83 | console.log(actual); 84 | console.error("Tokenization failed."); 85 | } else { 86 | console.log("Tokenization succeeded!") 87 | } 88 | }); -------------------------------------------------------------------------------- /test/tokenizer/test-writesWarningForNullWhenNullBehaviorIsWarn.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import fs = require('fs'); 5 | 6 | let rootDir = path.join(__dirname, '../../Tasks', 'Tokenizer'); 7 | let taskPath = path.join(rootDir, 'tokenizer.js'); 8 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 9 | 10 | // set up a tmp file for the test 11 | var workingFolder = path.join(__dirname, "working"); 12 | if (!fs.existsSync(workingFolder)) { 13 | fs.mkdirSync(workingFolder); 14 | } 15 | var tmpFile = path.join(workingFolder, "appsettings.json"); 16 | 17 | // provide answers for task mock 18 | let a: ma.TaskLibAnswers = { 19 | "checkPath": { 20 | "working": true 21 | }, 22 | "findMatch": { 23 | "appsettings.json" : [ tmpFile ] 24 | } 25 | }; 26 | tmr.setAnswers(a); 27 | 28 | fs.writeFile(tmpFile, ` 29 | { 30 | "ConnectionStrings": { 31 | "DefaultConnection": "Server=(localdb)\\\\mssqllocaldb;Database=aspnet-WebApplication1-26e8893e-d7c0-4fc6-8aab-29b59971d622;Trusted_Connection=True;MultipleActiveResultSets=true" 32 | }, 33 | "Tricky": { 34 | "Tricky": null, 35 | "Tricky1": { 36 | "Tricky2": "Tricky" 37 | } 38 | }, 39 | "Logging": { 40 | "IncludeScopes": false, 41 | "LogLevel": { 42 | "Default": "Debug", 43 | "System": "Information", 44 | "Microsoft": "Information" 45 | } 46 | } 47 | } 48 | `, (err) => { 49 | 50 | // set inputs 51 | tmr.setInput('sourcePath', "working"); 52 | tmr.setInput('filePattern', 'appsettings.json'); 53 | tmr.setInput('tokenizeType', 'Json'); 54 | tmr.setInput('includes', 'ConnectionStrings.DefaultConnection,Logging.LogLevel.Default'); 55 | tmr.setInput('excludes', ''); 56 | tmr.setInput('nullBehavior', 'warning'); 57 | 58 | tmr.run(); 59 | 60 | // validate the replacement 61 | let actual = fs.readFileSync(tmpFile).toString(); 62 | var expected = `{ 63 | "ConnectionStrings": { 64 | "DefaultConnection": "__ConnectionStrings.DefaultConnection__" 65 | }, 66 | "Tricky": { 67 | "Tricky": null, 68 | "Tricky1": { 69 | "Tricky2": "Tricky" 70 | } 71 | }, 72 | "Logging": { 73 | "IncludeScopes": false, 74 | "LogLevel": { 75 | "Default": "__Logging.LogLevel.Default__", 76 | "System": "Information", 77 | "Microsoft": "Information" 78 | } 79 | } 80 | }`; 81 | 82 | if (actual.trim() !== expected.trim()) { 83 | console.log(actual); 84 | console.error("Tokenization failed."); 85 | } else { 86 | console.log("Tokenization succeeded!") 87 | } 88 | }); -------------------------------------------------------------------------------- /test/tokenizer/working/appsettings.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "ConnectionStrings": { 4 | "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-WebApplication1-26e8893e-d7c0-4fc6-8aab-29b59971d622;Trusted_Connection=True;MultipleActiveResultSets=true" 5 | }, 6 | "Tricky": { 7 | "Tricky": null, 8 | "Tricky1": { 9 | "Tricky2": "Tricky" 10 | } 11 | }, 12 | "Logging": { 13 | "IncludeScopes": false, 14 | "LogLevel": { 15 | "Default": "Debug", 16 | "System": "Information", 17 | "Microsoft": "Information" 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/versionAssemblies/test-complex.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const fs = require("fs"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'VersionAssemblies'); 7 | let taskPath = path.join(rootDir, 'versionAssemblies.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // set up a tmp file for the test 10 | var workingFolder = path.join(__dirname, "working"); 11 | if (!fs.existsSync(workingFolder)) { 12 | fs.mkdirSync(workingFolder); 13 | } 14 | var tmpFile = path.join(workingFolder, "AndroidManifest.xml"); 15 | // provide answers for task mock 16 | let a = { 17 | "checkPath": { 18 | "working": true 19 | }, 20 | "findMatch": { 21 | "AndroidManifest.xml": [tmpFile] 22 | } 23 | }; 24 | tmr.setAnswers(a); 25 | fs.writeFile(tmpFile, ` 26 | 27 | 28 | 29 | 30 | 31 | `, (err) => { 32 | // set inputs 33 | tmr.setInput('sourcePath', "working"); 34 | tmr.setInput('filePattern', 'AndroidManifest.xml'); 35 | tmr.setInput("versionSource", 'buildNumer'); 36 | tmr.setInput("versionFormat", 'custom'); 37 | tmr.setInput("replaceVersionFormat", 'custom'); 38 | tmr.setInput('customBuildRegex', '(?:\\d+\\.\\d+\\.)(\\d+)'); 39 | tmr.setInput('buildRegexIndex', '1'); 40 | tmr.setInput('customReplaceRegex', 'versionCode="\\d+'); 41 | tmr.setInput('replacePrefix', 'versionCode="'); 42 | tmr.setInput('replacePostfix', '-alpha'); 43 | tmr.setInput('failIfNoMatchFound', 'false'); 44 | // set variables 45 | process.env["BUILD_BUILDNUMBER"] = "5.2.43"; 46 | tmr.run(); 47 | // validate the replacement 48 | let actual = fs.readFileSync(tmpFile).toString(); 49 | var expected = ` 50 | 51 | 52 | 53 | 54 | 55 | `; 56 | if (actual.trim() !== expected.trim()) { 57 | console.log(actual); 58 | console.error("Versioning failed."); 59 | } 60 | else { 61 | console.log("Versioning succeeded!"); 62 | } 63 | }); 64 | //# sourceMappingURL=test-complex.js.map -------------------------------------------------------------------------------- /test/versionAssemblies/test-complex.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import fs = require('fs'); 5 | 6 | let rootDir = path.join(__dirname, '../../Tasks', 'VersionAssemblies'); 7 | let taskPath = path.join(rootDir, 'versionAssemblies.js'); 8 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 9 | 10 | // set up a tmp file for the test 11 | var workingFolder = path.join(__dirname, "working"); 12 | if (!fs.existsSync(workingFolder)) { 13 | fs.mkdirSync(workingFolder); 14 | } 15 | var tmpFile = path.join(workingFolder, "AndroidManifest.xml"); 16 | 17 | // provide answers for task mock 18 | let a: ma.TaskLibAnswers = { 19 | "checkPath": { 20 | "working": true 21 | }, 22 | "findMatch": { 23 | "AndroidManifest.xml" : [ tmpFile ] 24 | } 25 | }; 26 | tmr.setAnswers(a); 27 | 28 | fs.writeFile(tmpFile, ` 29 | 30 | 31 | 32 | 33 | 34 | `, (err) => { 35 | 36 | // set inputs 37 | tmr.setInput('sourcePath', "working"); 38 | tmr.setInput('filePattern', 'AndroidManifest.xml'); 39 | tmr.setInput("versionSource", 'buildNumer'); 40 | tmr.setInput("versionFormat", 'custom'); 41 | tmr.setInput("replaceVersionFormat", 'custom'); 42 | tmr.setInput('customBuildRegex', '(?:\\d+\\.\\d+\\.)(\\d+)'); 43 | tmr.setInput('buildRegexIndex', '1'); 44 | tmr.setInput('customReplaceRegex', 'versionCode="\\d+'); 45 | tmr.setInput('replacePrefix', 'versionCode="'); 46 | tmr.setInput('replacePostfix', '-alpha'); 47 | tmr.setInput('failIfNoMatchFound', 'false'); 48 | 49 | // set variables 50 | process.env["BUILD_BUILDNUMBER"] = "5.2.43"; 51 | 52 | tmr.run(); 53 | 54 | // validate the replacement 55 | let actual = fs.readFileSync(tmpFile).toString(); 56 | var expected = ` 57 | 58 | 59 | 60 | 61 | 62 | `; 63 | 64 | if (actual.trim() !== expected.trim()) { 65 | console.log(actual); 66 | console.error("Versioning failed."); 67 | } else { 68 | console.log("Versioning succeeded!") 69 | } 70 | }); -------------------------------------------------------------------------------- /test/versionAssemblies/test-defaults3.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const fs = require("fs"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'VersionAssemblies'); 7 | let taskPath = path.join(rootDir, 'versionAssemblies.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // set up a tmp file for the test 10 | var workingFolder = path.join(__dirname, "working"); 11 | if (!fs.existsSync(workingFolder)) { 12 | fs.mkdirSync(workingFolder); 13 | } 14 | var tmpFile = path.join(workingFolder, "AssemblyInfo.cs"); 15 | // provide answers for task mock 16 | let a = { 17 | "checkPath": { 18 | "working": true 19 | }, 20 | "findMatch": { 21 | "**/AssemblyInfo.*": [tmpFile] 22 | } 23 | }; 24 | tmr.setAnswers(a); 25 | fs.writeFile(tmpFile, ` 26 | [assembly: AssemblyTitle("TestAsm")] 27 | [assembly: AssemblyProduct("TestAsm")] 28 | [assembly: AssemblyCopyright("Copyright © 2016")] 29 | // The following GUID is for the ID of the typelib if this project is exposed to COM 30 | [assembly: Guid("994fa927-3e6f-4794-a442-5003ca450d2b")] 31 | [assembly: AssemblyVersion("1.0.0.0")] 32 | [assembly: AssemblyFileVersion("1.0.0.0")] 33 | `, (err) => { 34 | // set inputs 35 | tmr.setInput('sourcePath', "working"); 36 | tmr.setInput('filePattern', '**/AssemblyInfo.*'); 37 | tmr.setInput("versionSource", 'buildNumer'); 38 | tmr.setInput("versionFormat", 'threeParts'); 39 | tmr.setInput("replaceVersionFormat", 'fourParts'); 40 | tmr.setInput('buildRegexIndex', '0'); 41 | tmr.setInput('replaceRegex', ''); 42 | tmr.setInput('replacePrefix', ''); 43 | tmr.setInput('replacePostfix', ''); 44 | tmr.setInput('failIfNoMatchFound', 'false'); 45 | // set variables 46 | process.env["BUILD_BUILDNUMBER"] = "1.5.2"; 47 | tmr.run(); 48 | // validate the replacement 49 | let actual = fs.readFileSync(tmpFile).toString(); 50 | var expected = ` 51 | [assembly: AssemblyTitle("TestAsm")] 52 | [assembly: AssemblyProduct("TestAsm")] 53 | [assembly: AssemblyCopyright("Copyright © 2016")] 54 | // The following GUID is for the ID of the typelib if this project is exposed to COM 55 | [assembly: Guid("994fa927-3e6f-4794-a442-5003ca450d2b")] 56 | [assembly: AssemblyVersion("1.5.2")] 57 | [assembly: AssemblyFileVersion("1.5.2")] 58 | `; 59 | if (actual.trim() !== expected.trim()) { 60 | console.log(actual); 61 | console.error("Versioning failed."); 62 | } 63 | else { 64 | console.log("Versioning succeeded!"); 65 | } 66 | }); 67 | //# sourceMappingURL=test-defaults3.js.map -------------------------------------------------------------------------------- /test/versionAssemblies/test-defaults4.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const fs = require("fs"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'VersionAssemblies'); 7 | let taskPath = path.join(rootDir, 'versionAssemblies.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // set up a tmp file for the test 10 | var workingFolder = path.join(__dirname, "working"); 11 | if (!fs.existsSync(workingFolder)) { 12 | fs.mkdirSync(workingFolder); 13 | } 14 | var tmpFile = path.join(workingFolder, "AssemblyInfo.cs"); 15 | // provide answers for task mock 16 | let a = { 17 | "checkPath": { 18 | "working": true 19 | }, 20 | "findMatch": { 21 | "**/AssemblyInfo.*": [tmpFile] 22 | } 23 | }; 24 | tmr.setAnswers(a); 25 | // mock the fs 26 | fs.writeFile(tmpFile, ` 27 | [assembly: AssemblyTitle("TestAsm")] 28 | [assembly: AssemblyProduct("TestAsm")] 29 | [assembly: AssemblyCopyright("Copyright © 2016")] 30 | // The following GUID is for the ID of the typelib if this project is exposed to COM 31 | [assembly: Guid("994fa927-3e6f-4794-a442-5003ca450d2b")] 32 | [assembly: AssemblyVersion("1.0.0.0")] 33 | [assembly: AssemblyFileVersion("1.0.0.0")] 34 | `, (err) => { 35 | // set inputs 36 | tmr.setInput('sourcePath', "working"); 37 | tmr.setInput('filePattern', '**/AssemblyInfo.*'); 38 | tmr.setInput("versionSource", 'buildNumer'); 39 | tmr.setInput("versionFormat", 'fourParts'); 40 | tmr.setInput("replaceVersionFormat", 'fourParts'); 41 | tmr.setInput('buildRegexIndex', '0'); 42 | tmr.setInput('replaceRegex', ''); 43 | tmr.setInput('replacePrefix', ''); 44 | tmr.setInput('replacePostfix', ''); 45 | tmr.setInput('failIfNoMatchFound', 'false'); 46 | // set variables 47 | process.env["BUILD_BUILDNUMBER"] = "1.5.2.3"; 48 | tmr.run(); 49 | // validate the replacement 50 | let actual = fs.readFileSync(tmpFile).toString(); 51 | var expected = ` 52 | [assembly: AssemblyTitle("TestAsm")] 53 | [assembly: AssemblyProduct("TestAsm")] 54 | [assembly: AssemblyCopyright("Copyright © 2016")] 55 | // The following GUID is for the ID of the typelib if this project is exposed to COM 56 | [assembly: Guid("994fa927-3e6f-4794-a442-5003ca450d2b")] 57 | [assembly: AssemblyVersion("1.5.2.3")] 58 | [assembly: AssemblyFileVersion("1.5.2.3")] 59 | `; 60 | if (actual.trim() !== expected.trim()) { 61 | console.log(actual); 62 | console.error("Versioning failed."); 63 | } 64 | else { 65 | console.log("Versioning succeeded!"); 66 | } 67 | }); 68 | //# sourceMappingURL=test-defaults4.js.map -------------------------------------------------------------------------------- /test/versionAssemblies/test-failIfNotFound.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tmrm = require("azure-pipelines-task-lib/mock-run"); 4 | const path = require("path"); 5 | const fs = require("fs"); 6 | let rootDir = path.join(__dirname, '../../Tasks', 'VersionAssemblies'); 7 | let taskPath = path.join(rootDir, 'versionAssemblies.js'); 8 | let tmr = new tmrm.TaskMockRunner(taskPath); 9 | // set up a tmp file for the test 10 | var workingFolder = path.join(__dirname, "working"); 11 | if (!fs.existsSync(workingFolder)) { 12 | fs.mkdirSync(workingFolder); 13 | } 14 | var tmpFile = path.join(workingFolder, "AssemblyInfo.cs"); 15 | // provide answers for task mock 16 | let a = { 17 | "checkPath": { 18 | "working": true 19 | }, 20 | "findMatch": { 21 | "**/AssemblyInfo.*": [tmpFile] 22 | } 23 | }; 24 | tmr.setAnswers(a); 25 | // mock the fs 26 | fs.writeFile(tmpFile, ` 27 | [assembly: AssemblyTitle("TestAsm")] 28 | [assembly: AssemblyProduct("TestAsm")] 29 | [assembly: AssemblyCopyright("Copyright © 2016")] 30 | // The following GUID is for the ID of the typelib if this project is exposed to COM 31 | [assembly: Guid("994fa927-3e6f-4794-a442-5003ca450d2b")] 32 | [assembly: AssemblyVersion("1.0.0")] 33 | [assembly: AssemblyFileVersion("1.0.0")] 34 | `, (err) => { 35 | // set inputs 36 | tmr.setInput('sourcePath', "working"); 37 | tmr.setInput('filePattern', '**/AssemblyInfo.*'); 38 | tmr.setInput('versionSource', 'buildNumber'); 39 | tmr.setInput('versionFormat', 'fourParts'); 40 | tmr.setInput('replaceVersionFormat', 'fourParts'); 41 | tmr.setInput('buildRegexIndex', '0'); 42 | tmr.setInput('replaceRegex', ''); 43 | tmr.setInput('replacePrefix', ''); 44 | tmr.setInput('replacePostfix', ''); 45 | tmr.setInput('failIfNoMatchFound', 'true'); 46 | // set variables 47 | process.env["BUILD_BUILDNUMBER"] = "1.5.2.3"; 48 | tmr.run(); 49 | }); 50 | //# sourceMappingURL=test-failIfNotFound.js.map -------------------------------------------------------------------------------- /test/versionAssemblies/test-failIfNotFound.ts: -------------------------------------------------------------------------------- 1 | import ma = require('azure-pipelines-task-lib/mock-answer'); 2 | import tmrm = require('azure-pipelines-task-lib/mock-run'); 3 | import path = require('path'); 4 | import fs = require('fs'); 5 | 6 | let rootDir = path.join(__dirname, '../../Tasks', 'VersionAssemblies'); 7 | let taskPath = path.join(rootDir, 'versionAssemblies.js'); 8 | let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); 9 | 10 | // set up a tmp file for the test 11 | var workingFolder = path.join(__dirname, "working"); 12 | if (!fs.existsSync(workingFolder)) { 13 | fs.mkdirSync(workingFolder); 14 | } 15 | var tmpFile = path.join(workingFolder, "AssemblyInfo.cs"); 16 | 17 | // provide answers for task mock 18 | let a: ma.TaskLibAnswers = { 19 | "checkPath": { 20 | "working": true 21 | }, 22 | "findMatch": { 23 | "**/AssemblyInfo.*" : [ tmpFile ] 24 | } 25 | }; 26 | tmr.setAnswers(a); 27 | 28 | // mock the fs 29 | fs.writeFile(tmpFile, ` 30 | [assembly: AssemblyTitle("TestAsm")] 31 | [assembly: AssemblyProduct("TestAsm")] 32 | [assembly: AssemblyCopyright("Copyright © 2016")] 33 | // The following GUID is for the ID of the typelib if this project is exposed to COM 34 | [assembly: Guid("994fa927-3e6f-4794-a442-5003ca450d2b")] 35 | [assembly: AssemblyVersion("1.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0")] 37 | `, (err) => { 38 | 39 | // set inputs 40 | tmr.setInput('sourcePath', "working"); 41 | tmr.setInput('filePattern', '**/AssemblyInfo.*'); 42 | tmr.setInput('versionSource', 'buildNumber'); 43 | tmr.setInput('versionFormat', 'fourParts'); 44 | tmr.setInput('replaceVersionFormat', 'fourParts'); 45 | tmr.setInput('buildRegexIndex', '0'); 46 | tmr.setInput('replaceRegex', ''); 47 | tmr.setInput('replacePrefix', ''); 48 | tmr.setInput('replacePostfix', ''); 49 | tmr.setInput('failIfNoMatchFound', 'true'); 50 | 51 | // set variables 52 | process.env["BUILD_BUILDNUMBER"] = "1.5.2.3"; 53 | 54 | tmr.run(); 55 | }); -------------------------------------------------------------------------------- /test/versionAssemblies/working/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /test/versionAssemblies/working/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | 2 | [assembly: AssemblyTitle("TestAsm")] 3 | [assembly: AssemblyProduct("TestAsm")] 4 | [assembly: AssemblyCopyright("Copyright © 2016")] 5 | // The following GUID is for the ID of the typelib if this project is exposed to COM 6 | [assembly: Guid("994fa927-3e6f-4794-a442-5003ca450d2b")] 7 | [assembly: AssemblyVersion("1.0.0")] 8 | [assembly: AssemblyFileVersion("1.0.0")] 9 | -------------------------------------------------------------------------------- /test/versionAssemblies/working/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | CFBundleDisplayName 7 | YourAppName 8 | CFBundleIdentifier 9 | com.example.yourappname 10 | CFBundleShortVersionString 11 | 2.16.2 12 | CFBundleVersion 13 | 5.2.43.112 14 | LSRequiresIPhoneOS 15 | 16 | MinimumOSVersion 17 | 9.0 18 | UIDeviceFamily 19 | 20 | 2 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "ES6", 5 | "sourceMap": true 6 | }, 7 | "exclude": [ 8 | "node_modules", 9 | "Tasks/VersionAssemblies/node_modules", 10 | "Tasks/Tokenizer/node_modules", 11 | "Tasks/ReplaceTokens/node_modules", 12 | "Tasks/CoverageGate/node_modules", 13 | "Tasks/TagBuild/node_modules", 14 | "Tasks/RouteTraffic/node_modules" 15 | ] 16 | } -------------------------------------------------------------------------------- /update-taskids.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | type=$1 4 | if [ $type = 'beta' ] ; then 5 | echo "Switching to beta ids" 6 | else 7 | if [ $type = 'prod' ] ; then 8 | echo "Switching to live ids" 9 | else 10 | echo "Unknown type: $type (should be 'beta' or 'prod')" 11 | exit 1 12 | fi 13 | fi 14 | 15 | for row in $(cat "./taskIds.json" | jq -c '.tasks[]'); do 16 | _jq() { 17 | echo ${row} | jq -r ${1} 18 | } 19 | 20 | # get the correct id 21 | newId=$(_jq '."beta-id"') 22 | if [ $type = 'prod' ] ; then 23 | newId=$(_jq '.id') 24 | fi 25 | 26 | # get the path to the task.json file 27 | fullTaskJsonPath=$PWD/$(_jq '.path')/task.json 28 | jq '.id = $newId' $fullTaskJsonPath --arg newId $newId > temp.json && mv temp.json $fullTaskJsonPath 29 | done --------------------------------------------------------------------------------