From 54108c642bd5841912b7e3d83cf0165b35f7cc25 Mon Sep 17 00:00:00 2001 From: David Kalmin Date: Tue, 10 May 2022 14:32:07 -0700 Subject: [PATCH] Initial commit to Valet Labs --- .devcontainer/devcontainer.json | 26 ++ .github/workflows/valetbsazdo.yml | 35 +++ azure_devops/bootstrap/azDevOps.ps1 | 167 ++++++++++++ azure_devops/bootstrap/updateEnvs.ps1 | 21 ++ .../pipelines/classic/valet-classic1.json | 243 ++++++++++++++++++ .../pipelines/classic/valet-classic2.json | 243 ++++++++++++++++++ azure_devops/pipelines/readme.md | 10 + .../pipelines/yml/valet-mapper-example.yml | 29 +++ .../pipelines/yml/valet-pipeline1.yml | 19 ++ .../pipelines/yml/valet-pipeline2.yml | 19 ++ azure_devops/readme.md | 111 ++++++++ azure_devops/valet-audit-lab.md | 44 ++++ azure_devops/valet-dry-run-lab.md | 49 ++++ azure_devops/valet-forecast-lab.md | 3 + azure_devops/valet-migrate-custom-lab.md | 88 +++++++ azure_devops/valet-migrate-lab.md | 49 ++++ code/Bootcamp.sln | 56 ++++ code/readme.md | 5 + code/src/Attendee/Attendee.cs | 15 ++ code/src/Attendee/Attendee.csproj | 7 + code/test/AttendeeTest/AttendeeExists.cs | 18 ++ code/test/AttendeeTest/AttendeeTest.csproj | 26 ++ jenkins/readme.md | 1 + readme.md | 16 ++ valet/.env.local | 6 + valet/valet | 27 ++ valet/valet-update | 10 + 27 files changed, 1343 insertions(+) create mode 100644 .devcontainer/devcontainer.json create mode 100644 .github/workflows/valetbsazdo.yml create mode 100644 azure_devops/bootstrap/azDevOps.ps1 create mode 100644 azure_devops/bootstrap/updateEnvs.ps1 create mode 100644 azure_devops/pipelines/classic/valet-classic1.json create mode 100644 azure_devops/pipelines/classic/valet-classic2.json create mode 100644 azure_devops/pipelines/readme.md create mode 100644 azure_devops/pipelines/yml/valet-mapper-example.yml create mode 100644 azure_devops/pipelines/yml/valet-pipeline1.yml create mode 100644 azure_devops/pipelines/yml/valet-pipeline2.yml create mode 100644 azure_devops/readme.md create mode 100644 azure_devops/valet-audit-lab.md create mode 100644 azure_devops/valet-dry-run-lab.md create mode 100644 azure_devops/valet-forecast-lab.md create mode 100644 azure_devops/valet-migrate-custom-lab.md create mode 100644 azure_devops/valet-migrate-lab.md create mode 100644 code/Bootcamp.sln create mode 100644 code/readme.md create mode 100644 code/src/Attendee/Attendee.cs create mode 100644 code/src/Attendee/Attendee.csproj create mode 100644 code/test/AttendeeTest/AttendeeExists.cs create mode 100644 code/test/AttendeeTest/AttendeeTest.csproj create mode 100644 jenkins/readme.md create mode 100644 readme.md create mode 100644 valet/.env.local create mode 100644 valet/valet create mode 100644 valet/valet-update diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..3e2e04b --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,26 @@ +{ + "name": "Codespace to bootstrap valet in a Codespace", + //Use base codespace image then pull Valet on postCreateCommand, + "image": "mcr.microsoft.com/vscode/devcontainers/universal:linux", + "remoteUser": "codespace", + "overrideCommand": false, + "mounts": ["source=codespaces-linux-var-lib-docker,target=/var/lib/docker,type=volume"], + "runArgs": [ + "--cap-add=SYS_PTRACE", + "--security-opt", + "seccomp=unconfined", + "--privileged", + "--init" + ], + + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "GitHub.vscode-pull-request-github", + "ms-vscode.azure-account", + "ms-vscode.azurecli", + "ms-azure-devops.azure-pipelines", + "ms-azuretools.vscode-docker", + "ms-vscode.powershell" + ], + "postCreateCommand": "docker login ghcr.io/valet-customers --username ${GITHUB_USER} --password ${VALET_PASSWORD} && docker pull ghcr.io/valet-customers/valet-cli:latest && chmod +x ./valet/valet-update && chmod +x ./valet/valet && pwsh ./azure_devops/bootstrap/updateEnvs.ps1 -ghPAT ${VALET_PASSWORD} -azdoPAT ${AZDO_TOKEN} -org ${AZDO_ORG} -proj ${AZDO_PROJECT} || echo 'Could not auto-build. Skipping.' " +} diff --git a/.github/workflows/valetbsazdo.yml b/.github/workflows/valetbsazdo.yml new file mode 100644 index 0000000..46d9750 --- /dev/null +++ b/.github/workflows/valetbsazdo.yml @@ -0,0 +1,35 @@ +# This is a workflow to set up an Azure DevOps instance seeded with pipelines +# You need to Add a secret for an Azure DevOps PAT called AZDOPAT + +name: Valet Bootstrap for Azure DevOps + +on: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + inputs: + AzDoOrgName: + description: 'Azure DevOps organization name' + required: true + type: string + AzDoUserName: + description: 'Azure DevOps user name' + required: true + type: string + AzDoProjectName: + description: 'Azure DevOps project name' + default: 'ValetBootstrap' + type: string +jobs: + bootstrap: + name: Bootstrap + runs-on: windows-latest + steps: + - name: Check out repository code + uses: actions/checkout@v2 + - name: Run powershell file to bootstrap Azure DevOps + env: + AZDOPATTOUSE: ${{ secrets.AZDOPAT }} + ROOTFOLDER: ${{ github.workspace }} + shell: pwsh + run: | + ./azure_devops/bootstrap/azDevOps.ps1 -project ${{ github.event.inputs.AzDoProjectName }} -userName ${{ github.event.inputs.AzDoUserName }} -repoName ${{ github.event.inputs.AzDoProjectName }} -orgToUse ${{ github.event.inputs.AzDoOrgName }} -rootFolder $env:ROOTFOLDER -daPassword $env:AZDOPATTOUSE diff --git a/azure_devops/bootstrap/azDevOps.ps1 b/azure_devops/bootstrap/azDevOps.ps1 new file mode 100644 index 0000000..626de9e --- /dev/null +++ b/azure_devops/bootstrap/azDevOps.ps1 @@ -0,0 +1,167 @@ +param ( + $project = "ValetBootstrap", + $repoName = "ValetBootstrap", + $codeFolder= "code,azure_devops/pipelines", + $rootFolder= ".", + $pipelinesRoot="azure_devops/pipelines", + [String]$orgToUse = "..", + [String]$userName=$(Throw "Azure DevOps Username required."), + [String]$daPassword=$(Throw "Password required.") + ) + +Write-Host "Start Valet Bootstrap" +Write-Host "Azure DevOps Organization to use $orgToUse" +Write-Host "Azure DevOps Project to use $project" +Write-Host "Repo Name $repoName" +Write-Host "Code Folders: $codeFolder" +Write-Host "Root Folders: $rootFolder" +Write-Host "Pipelines Folders: $pipelinesRoot" +Write-Host "Azure DevOps username to authenticate with $userName" +Write-Host "Azure DevOps PAT to authenticate with $daPassword" + +function Get-BasicAuthCreds { + param([string]$Username,[String]$Password) + $AuthString = "{0}:{1}" -f $Username,$Password + $AuthBytes = [System.Text.Encoding]::Ascii.GetBytes($AuthString) + return [Convert]::ToBase64String($AuthBytes) +} + +#Get the creds to use in all GitHub API calls. +$BasicCreds = Get-BasicAuthCreds -Username "$userName" -Password $daPassword + +########################################################################## +#CREATE THE AZURE DEVOPS PROJECT +$createtUrlToUse = [string]::Format("https://dev.azure.com/{0}/_apis/projects?api-version=6.0", $orgToUse) + +$projectToCreate = @{ + "name"= "$project" + "description"= "Project to be used for Valet Demos" + "capabilities"= @{ + "versioncontrol"= @{ + "sourceControlType"= "Git" + } + "processTemplate"= @{ + "templateTypeId"= "6b724908-ef14-45cf-84f8-768b5384da45" + } + } + } + +$projectResponse = Invoke-RestMethod -Method 'Post' -Uri $createtUrlToUse -Headers @{"Authorization"="Basic $BasicCreds"} -Body ($projectToCreate|ConvertTo-Json) -ContentType "application/json" +$projectResponse | ConvertTo-Json + +Start-Sleep -s 5 +Write-Host "Yes! Project $project was created!" + +########################################################################## +# IMPORT THE REPO +Set-Location $rootFolder + +[array]$folderArray = $codeFolder.Split(",") + +$addTextFile = @{ + "refUpdates"= @( + @{ + "name"= "refs/heads/main" + "oldObjectId"= "0000000000000000000000000000000000000000" + } + ) + "commits"= @( + @{ + "comment"= "Initial commit." + "changes"= @( + foreach ($folder in $folderArray) + { + $codeRootFolder = Join-Path -Path $rootFolder -ChildPath $folder + Write-Host "codeRootFolder: $codeRootFolder" + + $itemPath = $folder.Substring($folder.lastIndexOf('/') + 1) + Write-Host "itemPath: $itemPath" + + $codeFiles = (Get-ChildItem "$codeRootFolder" -Recurse -Attributes !Directory) + foreach ($codeFile in $codeFiles ) { + $daFullName = $codeFile.FullName + $codeBody = (Get-Content "$daFullName" -Raw) + #Write-Host "codeBody: $codeBody" + Write-Host "folder: $folder" + $relath = $daFullName | Resolve-Path -Relative + Write-Host "relath: $relath" + $replaceSlash = $folder.Replace("/", "\") + $repoPath = $relath.Substring($relath.lastIndexOf($replaceSlash) + $replaceSlash.Length) + $wholeRepoPath = Join-Path -Path $itemPath -ChildPath $repoPath + $wholeRepoPath = $wholeRepoPath.Replace("\", "/") + Write-Host "wholeRepoPath: $wholeRepoPath" + Write-Host "repoPath: $repoPath" + @{ + "changeType"= "add" + "item"= @{ + "path"= "/$wholeRepoPath" + } + "newContent"= @{ + "content"= "$codeBody" + "contentType"= "rawtext" + } + } + } + } + ) + } + ) + } + + +$repoUrlToUse = [string]::Format("https://dev.azure.com/{0}/{2}/_apis/git/repositories/{1}/pushes?api-version=7.1-preview.2", $orgToUse, $repoName, $project) +$pushResponse = Invoke-RestMethod -Method 'Post' -Uri $repoUrlToUse -Headers @{"Authorization"="Basic $BasicCreds"} -Body ($addTextFile|ConvertTo-Json -Depth 5) -ContentType "application/json" +$repoIds = $pushResponse.repository.id +Write-Host "Yes! Repo Was was created!" + +Write-Host "Yes! Repo was imported into $repoIds" + +########################################################################## +########################################################################## +# Create YML Pipelines +$plUrlToUse = [string]::Format("https://dev.azure.com/{0}/{1}/_apis/pipelines?api-version=6.0-preview.1", $orgToUse, "$project") + +$files = Get-ChildItem ".\$pipelinesRoot\yml\" +foreach ($f in $files) +{ + $nameOfPl = $f.BaseName + $fileName = $f.Name + Write-Host "basename: $nameOfPl filename: $fileName" + + $pipelineCreateBody = @{ + "folder"= "pipelines" + "name"= "$nameOfPl" + "configuration"= @{ + "type"= "yaml" + "path"= "/pipelines/yml/$fileName" + "repository"= @{ + "id"= "$repoIds" + "name"= "$repoName" + "type"= "azureReposGit" + } + } + } + #$pipelineCreateBody | ConvertTo-Json + + $repoResponse = Invoke-RestMethod -Method 'Post' -Uri $plUrlToUse -Headers @{"Authorization"="Basic $BasicCreds"} -Body ($pipelineCreateBody|ConvertTo-Json) -ContentType "application/json" + $repoResponse | ConvertTo-Json +} + +########################################################################## +#CREATE CLASSIC PIPELINEs + +$classicUrlToUse = [string]::Format("https://dev.azure.com/{0}/{1}/_apis/build/definitions?api-version=7.1-preview.7", $orgToUse, "$project") + +$files = Get-ChildItem ".\$pipelinesRoot\classic\" +foreach ($f in $files) +{ + $nameOfPl = $f.BaseName + $fileName = $f.Name + Write-Host "basename: $nameOfPl filename: $fileName" + + $pclassicreateBody = (Get-Content ./$pipelinesRoot/classic/$fileName).Replace("REPOTOREPLACE", "$repoName") + + $repo2Response = Invoke-RestMethod -Method 'Post' -Uri $classicUrlToUse -Headers @{"Authorization"="Basic $BasicCreds"} -Body ($pclassicreateBody) -ContentType "application/json" + $repo2Response | ConvertTo-Json +} +Write-Host "End Valet Bootstrap" diff --git a/azure_devops/bootstrap/updateEnvs.ps1 b/azure_devops/bootstrap/updateEnvs.ps1 new file mode 100644 index 0000000..04bbaec --- /dev/null +++ b/azure_devops/bootstrap/updateEnvs.ps1 @@ -0,0 +1,21 @@ +param ( + [String]$proj = "ValetBootstrapper", + [String]$org = "microsoft-bootcamp", + [String]$ghPAT = "dkalmintest", + [String]$azdoPAT = "dkalmin@github.com" + ) + +[String]$azdoProject = "AZURE_DEVOPS_PROJECT=" +[String]$azdoOrg = "AZURE_DEVOPS_ORGANIZATION=" +[String]$azdoInstance = "AZURE_DEVOPS_INSTANCE_URL=" +[String]$ghAccess = "GITHUB_ACCESS_TOKEN=" +[String]$azdoAccess = "AZURE_DEVOPS_ACCESS_TOKEN=" + +$updateEnvs = (Get-Content ./valet/.env.local) + +$updateEnvs = $updateEnvs.Replace("$azdoProject", "AZURE_DEVOPS_PROJECT=$proj") +$updateEnvs = $updateEnvs.Replace("$azdoOrg", "AZURE_DEVOPS_ORGANIZATION=$org") +$updateEnvs = $updateEnvs.Replace("$azdoInstance", "AZURE_DEVOPS_INSTANCE_URL=https://dev.azure.com/$org") +$updateEnvs = $updateEnvs.Replace("$ghAccess", "GITHUB_ACCESS_TOKEN=$ghPAT") +$updateEnvs = $updateEnvs.Replace("$azdoAccess", "AZURE_DEVOPS_ACCESS_TOKEN=$azdoPAT") +Set-Content -Path ./valet/.env.local -Value $updateEnvs diff --git a/azure_devops/pipelines/classic/valet-classic1.json b/azure_devops/pipelines/classic/valet-classic1.json new file mode 100644 index 0000000..1ade862 --- /dev/null +++ b/azure_devops/pipelines/classic/valet-classic1.json @@ -0,0 +1,243 @@ +{ + "options": [ + { + "enabled": true, + "definition": { + "id": "5d58cc01-7c75-450c-be18-a388ddb129ec" + }, + "inputs": { + "branchFilters": "[\"+refs/heads/*\"]", + "additionalFields": "{}" + } + }, + { + "enabled": false, + "definition": { + "id": "a9db38f9-9fdc-478c-b0f9-464221e58316" + }, + "inputs": { + "workItemType": "Task", + "assignToRequestor": "true", + "additionalFields": "{}" + } + } + ], + "variables": { + "BuildConfiguration": { + "value": "release", + "allowOverride": true + }, + "BuildPlatform": { + "value": "any cpu", + "allowOverride": true + }, + "system.debug": { + "value": "false", + "allowOverride": true + } + }, + "properties": {}, + "tags": [], + "_links": [], + "buildNumberFormat": "$(date:yyyyMMdd)$(rev:.r)", + "jobAuthorizationScope": 1, + "jobTimeoutInMinutes": 60, + "jobCancelTimeoutInMinutes": 5, + "process": { + "phases": [ + { + "steps": [ + { + "environment": {}, + "enabled": true, + "continueOnError": false, + "alwaysRun": false, + "displayName": "Use NuGet 4.4.1", + "timeoutInMinutes": 0, + "retryCountOnTaskFailure": 0, + "condition": "succeeded()", + "task": { + "id": "2c65196a-54fd-4a02-9be8-d9d1837b7c5d", + "versionSpec": "0.*", + "definitionType": "task" + }, + "inputs": { + "versionSpec": "4.4.1", + "checkLatest": "false" + } + }, + { + "environment": {}, + "enabled": true, + "continueOnError": false, + "alwaysRun": false, + "displayName": "NuGet restore", + "timeoutInMinutes": 0, + "retryCountOnTaskFailure": 0, + "condition": "succeeded()", + "task": { + "id": "333b11bd-d341-40d9-afcf-b32d5ce6f23b", + "versionSpec": "2.*", + "definitionType": "task" + }, + "inputs": { + "command": "restore", + "solution": "$(Parameters.solution)", + "selectOrConfig": "select", + "feedRestore": "", + "includeNuGetOrg": "true", + "nugetConfigPath": "", + "externalEndpoints": "", + "noCache": "false", + "disableParallelProcessing": "false", + "packagesDirectory": "", + "verbosityRestore": "Detailed", + "searchPatternPush": "$(Build.ArtifactStagingDirectory)/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/**/*.symbols.nupkg", + "nuGetFeedType": "internal", + "feedPublish": "", + "publishPackageMetadata": "true", + "allowPackageConflicts": "false", + "externalEndpoint": "", + "verbosityPush": "Detailed", + "searchPatternPack": "**/*.csproj", + "configurationToPack": "$(BuildConfiguration)", + "outputDir": "$(Build.ArtifactStagingDirectory)", + "versioningScheme": "off", + "includeReferencedProjects": "false", + "versionEnvVar": "", + "requestedMajorVersion": "1", + "requestedMinorVersion": "0", + "requestedPatchVersion": "0", + "packTimezone": "utc", + "includeSymbols": "false", + "toolPackage": "false", + "buildProperties": "", + "basePath": "", + "verbosityPack": "Detailed", + "arguments": "" + } + }, + { + "environment": {}, + "enabled": true, + "continueOnError": false, + "alwaysRun": false, + "displayName": "PowerShell Script", + "timeoutInMinutes": 0, + "retryCountOnTaskFailure": 0, + "condition": "succeeded()", + "task": { + "id": "e213ff0f-5d5c-4791-802d-52ea3e7be1f1", + "versionSpec": "2.*", + "definitionType": "task" + }, + "inputs": { + "targetType": "inline", + "filePath": "", + "arguments": "", + "script": "# Write your PowerShell commands here.\n\nWrite-Host \"Hello World\"\n", + "errorActionPreference": "stop", + "warningPreference": "default", + "informationPreference": "default", + "verbosePreference": "default", + "debugPreference": "default", + "failOnStderr": "false", + "showWarnings": "false", + "ignoreLASTEXITCODE": "false", + "pwsh": "false", + "workingDirectory": "", + "runScriptInSeparateScope": "false" + } + } + ], + "name": "Agent job 1", + "refName": "Job_1", + "condition": "succeeded()", + "target": { + "executionOptions": { + "type": 0 + }, + "allowScriptsAuthAccessOption": false, + "type": 1 + }, + "jobAuthorizationScope": 1 + } + ], + "target": { + "agentSpecification": { + "identifier": "windows-latest" + } + }, + "type": 1 + }, + "repository": { + "properties": { + "cleanOptions": "0", + "labelSources": "0", + "labelSourcesFormat": "$(build.buildNumber)", + "reportBuildStatus": "true", + "gitLfsSupport": "false", + "skipSyncSource": "false", + "checkoutNestedSubmodules": "false", + "fetchDepth": "0" + }, + "id": "", + "type": "TfsGit", + "name": "REPOTOREPLACE", + "url": "", + "defaultBranch": "refs/heads/main", + "clean": "false", + "checkoutSubmodules": false + }, + "processParameters": { + "inputs": [ + { + "aliases": [], + "options": {}, + "properties": {}, + "name": "solution", + "label": "Solution", + "defaultValue": "**\\*.sln", + "required": true, + "type": "filePath", + "helpMarkDown": "The path to the Visual Studio solution file or NuGet packages.config. Wildcards can be used. For example, `**\\\\*.sln` for all sln files in all sub folders." + } + ] + }, + "quality": 1, + "authoredBy": { + "displayName": "David Kalmin", + "url": "https://spsprodcus5.vssps.visualstudio.com/A8ceff4ff-6429-4de3-9c39-fd7f0b1fb05a/_apis/Identities/a886d3a4-5700-6920-a3e4-6dadf46e7614", + "_links": { + "avatar": { + "href": "https://dev.azure.com/microsoft-bootcamp/_apis/GraphProfile/MemberAvatars/aad.YTg4NmQzYTQtNTcwMC03OTIwLWEzZTQtNmRhZGY0NmU3NjE0" + } + }, + "id": "a886d3a4-5700-6920-a3e4-6dadf46e7614", + "uniqueName": "davidkalmin@microsoft.com", + "imageUrl": "https://dev.azure.com/microsoft-bootcamp/_apis/GraphProfile/MemberAvatars/aad.YTg4NmQzYTQtNTcwMC03OTIwLWEzZTQtNmRhZGY0NmU3NjE0", + "descriptor": "aad.YTg4NmQzYTQtNTcwMC03OTIwLWEzZTQtNmRhZGY0NmU3NjE0" + }, + "drafts": [], + "queue": { + "_links": { + "self": { + "href": "https://dev.azure.com/microsoft-bootcamp/_apis/build/Queues/126" + } + }, + "name": "Azure Pipelines", + "url": "https://dev.azure.com/microsoft-bootcamp/_apis/build/Queues/126", + "pool": { + "name": "Azure Pipelines", + "isHosted": true + } + }, + "id": 10, + "name": "valet-classic-test-import1", + "uri": "vstfs:///Build/Definition/10", + "path": "\\", + "type": 2, + "queueStatus": 0, + "revision": 1, + "createdDate": "2022-02-17T19:05:52.500Z", +} diff --git a/azure_devops/pipelines/classic/valet-classic2.json b/azure_devops/pipelines/classic/valet-classic2.json new file mode 100644 index 0000000..fa966c1 --- /dev/null +++ b/azure_devops/pipelines/classic/valet-classic2.json @@ -0,0 +1,243 @@ +{ + "options": [ + { + "enabled": true, + "definition": { + "id": "5d58cc01-7c75-450c-be18-a388ddb129ec" + }, + "inputs": { + "branchFilters": "[\"+refs/heads/*\"]", + "additionalFields": "{}" + } + }, + { + "enabled": false, + "definition": { + "id": "a9db38f9-9fdc-478c-b0f9-464221e58316" + }, + "inputs": { + "workItemType": "Task", + "assignToRequestor": "true", + "additionalFields": "{}" + } + } + ], + "variables": { + "BuildConfiguration": { + "value": "release", + "allowOverride": true + }, + "BuildPlatform": { + "value": "any cpu", + "allowOverride": true + }, + "system.debug": { + "value": "false", + "allowOverride": true + } + }, + "properties": {}, + "tags": [], + "_links": [], + "buildNumberFormat": "$(date:yyyyMMdd)$(rev:.r)", + "jobAuthorizationScope": 1, + "jobTimeoutInMinutes": 60, + "jobCancelTimeoutInMinutes": 5, + "process": { + "phases": [ + { + "steps": [ + { + "environment": {}, + "enabled": true, + "continueOnError": false, + "alwaysRun": false, + "displayName": "Use NuGet 4.4.1", + "timeoutInMinutes": 0, + "retryCountOnTaskFailure": 0, + "condition": "succeeded()", + "task": { + "id": "2c65196a-54fd-4a02-9be8-d9d1837b7c5d", + "versionSpec": "0.*", + "definitionType": "task" + }, + "inputs": { + "versionSpec": "4.4.1", + "checkLatest": "false" + } + }, + { + "environment": {}, + "enabled": true, + "continueOnError": false, + "alwaysRun": false, + "displayName": "NuGet restore", + "timeoutInMinutes": 0, + "retryCountOnTaskFailure": 0, + "condition": "succeeded()", + "task": { + "id": "333b11bd-d341-40d9-afcf-b32d5ce6f23b", + "versionSpec": "2.*", + "definitionType": "task" + }, + "inputs": { + "command": "restore", + "solution": "$(Parameters.solution)", + "selectOrConfig": "select", + "feedRestore": "", + "includeNuGetOrg": "true", + "nugetConfigPath": "", + "externalEndpoints": "", + "noCache": "false", + "disableParallelProcessing": "false", + "packagesDirectory": "", + "verbosityRestore": "Detailed", + "searchPatternPush": "$(Build.ArtifactStagingDirectory)/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/**/*.symbols.nupkg", + "nuGetFeedType": "internal", + "feedPublish": "", + "publishPackageMetadata": "true", + "allowPackageConflicts": "false", + "externalEndpoint": "", + "verbosityPush": "Detailed", + "searchPatternPack": "**/*.csproj", + "configurationToPack": "$(BuildConfiguration)", + "outputDir": "$(Build.ArtifactStagingDirectory)", + "versioningScheme": "off", + "includeReferencedProjects": "false", + "versionEnvVar": "", + "requestedMajorVersion": "1", + "requestedMinorVersion": "0", + "requestedPatchVersion": "0", + "packTimezone": "utc", + "includeSymbols": "false", + "toolPackage": "false", + "buildProperties": "", + "basePath": "", + "verbosityPack": "Detailed", + "arguments": "" + } + }, + { + "environment": {}, + "enabled": true, + "continueOnError": false, + "alwaysRun": false, + "displayName": "PowerShell Script", + "timeoutInMinutes": 0, + "retryCountOnTaskFailure": 0, + "condition": "succeeded()", + "task": { + "id": "e213ff0f-5d5c-4791-802d-52ea3e7be1f1", + "versionSpec": "2.*", + "definitionType": "task" + }, + "inputs": { + "targetType": "inline", + "filePath": "", + "arguments": "", + "script": "# Write your PowerShell commands here.\n\nWrite-Host \"Hello World\"\n", + "errorActionPreference": "stop", + "warningPreference": "default", + "informationPreference": "default", + "verbosePreference": "default", + "debugPreference": "default", + "failOnStderr": "false", + "showWarnings": "false", + "ignoreLASTEXITCODE": "false", + "pwsh": "false", + "workingDirectory": "", + "runScriptInSeparateScope": "false" + } + } + ], + "name": "Agent job 1", + "refName": "Job_1", + "condition": "succeeded()", + "target": { + "executionOptions": { + "type": 0 + }, + "allowScriptsAuthAccessOption": false, + "type": 1 + }, + "jobAuthorizationScope": 1 + } + ], + "target": { + "agentSpecification": { + "identifier": "windows-latest" + } + }, + "type": 1 + }, + "repository": { + "properties": { + "cleanOptions": "0", + "labelSources": "0", + "labelSourcesFormat": "$(build.buildNumber)", + "reportBuildStatus": "true", + "gitLfsSupport": "false", + "skipSyncSource": "false", + "checkoutNestedSubmodules": "false", + "fetchDepth": "0" + }, + "id": "", + "type": "TfsGit", + "name": "REPOTOREPLACE", + "url": "", + "defaultBranch": "refs/heads/main", + "clean": "false", + "checkoutSubmodules": false + }, + "processParameters": { + "inputs": [ + { + "aliases": [], + "options": {}, + "properties": {}, + "name": "solution", + "label": "Solution", + "defaultValue": "**\\*.sln", + "required": true, + "type": "filePath", + "helpMarkDown": "The path to the Visual Studio solution file or NuGet packages.config. Wildcards can be used. For example, `**\\\\*.sln` for all sln files in all sub folders." + } + ] + }, + "quality": 1, + "authoredBy": { + "displayName": "David Kalmin", + "url": "https://spsprodcus5.vssps.visualstudio.com/A8ceff4ff-6429-4de3-9c39-fd7f0b1fb05a/_apis/Identities/a886d3a4-5700-6920-a3e4-6dadf46e7614", + "_links": { + "avatar": { + "href": "https://dev.azure.com/microsoft-bootcamp/_apis/GraphProfile/MemberAvatars/aad.YTg4NmQzYTQtNTcwMC03OTIwLWEzZTQtNmRhZGY0NmU3NjE0" + } + }, + "id": "a886d3a4-5700-6920-a3e4-6dadf46e7614", + "uniqueName": "davidkalmin@microsoft.com", + "imageUrl": "https://dev.azure.com/microsoft-bootcamp/_apis/GraphProfile/MemberAvatars/aad.YTg4NmQzYTQtNTcwMC03OTIwLWEzZTQtNmRhZGY0NmU3NjE0", + "descriptor": "aad.YTg4NmQzYTQtNTcwMC03OTIwLWEzZTQtNmRhZGY0NmU3NjE0" + }, + "drafts": [], + "queue": { + "_links": { + "self": { + "href": "https://dev.azure.com/microsoft-bootcamp/_apis/build/Queues/126" + } + }, + "name": "Azure Pipelines", + "url": "https://dev.azure.com/microsoft-bootcamp/_apis/build/Queues/126", + "pool": { + "name": "Azure Pipelines", + "isHosted": true + } + }, + "id": 10, + "name": "valet-classic-test-import2", + "uri": "vstfs:///Build/Definition/10", + "path": "\\", + "type": 2, + "queueStatus": 0, + "revision": 1, + "createdDate": "2022-02-17T19:05:52.500Z", +} diff --git a/azure_devops/pipelines/readme.md b/azure_devops/pipelines/readme.md new file mode 100644 index 0000000..40258f9 --- /dev/null +++ b/azure_devops/pipelines/readme.md @@ -0,0 +1,10 @@ +# pipelines folder +This folder contains Azure DevOps pipelines that gets migrated to the Azure DevOps instance. + +### Note any file added to this folder or sub folders will get migrated to the Azure DevOps instance when the GitHub Action runs to create and bootstrap the Azure DevOps project + +## classic folder +The classic folder contains classic style Azure DevOps pipelines that are pure JSON files. + +## yml folder +The yml folder contains yml Azure DevOps pipelines. diff --git a/azure_devops/pipelines/yml/valet-mapper-example.yml b/azure_devops/pipelines/yml/valet-mapper-example.yml new file mode 100644 index 0000000..8220c95 --- /dev/null +++ b/azure_devops/pipelines/yml/valet-mapper-example.yml @@ -0,0 +1,29 @@ +--- +variables: +- name: BuildParameters.RESTOREBUILDPROJECTS + value: "**/*.csproj" +- name: BUILDCONFIGURATION + value: Release +name: "$(date:yyyyMMdd)$(rev:.r)" +jobs: +- job: Job_1 + displayName: Agent job 1 + pool: + vmImage: windows-latest + steps: + - checkout: self + - task: NodeTool@0 + displayName: Use Node 10.16.3 + inputs: + versionSpec: 10.16.3 + - task: DotNetCoreCLI@2 + displayName: Restore + inputs: + command: restore + projects: "$(BuildParameters.RESTOREBUILDPROJECTS)" + - task: DotNetCoreCLI@2 + displayName: Build + inputs: + projects: "$(BuildParameters.RESTOREBUILDPROJECTS)" + arguments: "--configuration $(BUILDCONFIGURATION)" + diff --git a/azure_devops/pipelines/yml/valet-pipeline1.yml b/azure_devops/pipelines/yml/valet-pipeline1.yml new file mode 100644 index 0000000..9c86c9a --- /dev/null +++ b/azure_devops/pipelines/yml/valet-pipeline1.yml @@ -0,0 +1,19 @@ +# Bootcap Starter pipeline +# Start with a minimal pipeline that you can customize to build and deploy your code. +# Add steps that build, run tests, deploy, and more: +# https://aka.ms/yaml + +trigger: +- main + +pool: + vmImage: windows-latest + +steps: +- script: echo Hello, I am pipeline 1! + displayName: 'Run a one-line script' + +- script: | + echo Add other tasks to build, test, and deploy your project. + echo See https://aka.ms/yaml + displayName: 'Run a multi-line script' diff --git a/azure_devops/pipelines/yml/valet-pipeline2.yml b/azure_devops/pipelines/yml/valet-pipeline2.yml new file mode 100644 index 0000000..8b801c9 --- /dev/null +++ b/azure_devops/pipelines/yml/valet-pipeline2.yml @@ -0,0 +1,19 @@ +# Bootcap Starter pipeline +# Start with a minimal pipeline that you can customize to build and deploy your code. +# Add steps that build, run tests, deploy, and more: +# https://aka.ms/yaml + +trigger: +- main + +pool: + vmImage: windows-latest + +steps: +- script: echo Hello, I am pipeline 2! + displayName: 'Run a one-line script' + +- script: | + echo Add other tasks to build, test, and deploy your project. + echo See https://aka.ms/yaml + displayName: 'Run a multi-line script' diff --git a/azure_devops/readme.md b/azure_devops/readme.md new file mode 100644 index 0000000..1c3ebdb --- /dev/null +++ b/azure_devops/readme.md @@ -0,0 +1,111 @@ +# Valet labs for Azure DevOps + +This lab bootstraps a Valet environment using GitHub Codespaces and enables you to create an Azure DevOps project against which to run the Valet CI/CD migration tool. + +- [Use this Repo as a template](#repo-template) +- [Prerequisites](#prerequisites) +- [Azure DevOps project creation](#azure-devops-project-creation) +- [Use Valet with a codespace](#use-valet-with-a-codespace) +- [Labs for Azure DevOps](#labs-for-azure-devops) + +## Repo template + +1. Click `Use this template` to create this repository inside your GitHub organization. + +## Prerequisites +1. Azure DevOps organization. Please identify or create an Azure DevOps organization to use: [Click to create an Azure DevOps Org](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/create-organization?toc=%2Fazure%2Fdevops%2Fget-started%2Ftoc.json&bc=%2Fazure%2Fdevops%2Fget-started%2Fbreadcrumb%2Ftoc.json&view=azure-devops) + - Note and store the organization name for later. +2. Create an Azure DevOps personal access token with the following scopes: + - To do so, navigate to Sign in to your organization `https://dev.azure.com/{yourorganization}`. + - From your home page, open `user settings`, and then select `Personal access tokens`. + - Select `+ New Token` + - Name your token, select the organization where you want to use the token, and then set your token to automatically expire after a set number of days. + - Select the following scopes: + - Agents Pool: `Read` + - Build: `Read & Execute` + - Code: `Full, Execute` + - Project and Team: `Read, Write, & Manage` + - Release: `Read` + - Service Connections: `Read` + - Variable Groups: `Read` + - Click `Create` + - Copy the PAT somewhere safe and temporary. +3. Create a GitHub personal access token. + - To do so, navigate to your GitHub `Settings` - click your profile photo and then click `Settings`. + - Go to `Developer Settings` + - Go to `Personal Access Tokens` -> `Legacy tokens` + - Click `Generate new token` -> `Legacy tokens`. If required, provide your password. + - Select at least these scopes: `read packages` and `workflow`. Optionally, provide a text in the **Note** field and change the expiration. + - Click `Generate token` + - Copy the PAT somewhere safe and temporary. +4. Add GitHub personal access token to the CODESPACES **Secrets** tab. + - Navigate to the `Settings` tab in your repo + - Find `Secrets` and click the down arrow + - Click `Codespaces` + - Click `New Codespaces Secret` to create a new secret. + - Name the secret `VALET_PASSWORD` + - Paste in the GitHub PAT generated previously + - Click `Add Secret` + +## Azure DevOps project creation + +1. Add your Azure DevOps personal access token to the Actions **Secrets** tab. + - Navigate to the `Settings` tab in this repo + - Find `Secrets` and click the down arrow + - Click `Actions` + - Click `New Repository Secret` to create a new secret. + - Name the secret `AZDOPAT` + - Paste in the Azure DevOps PAT generated previously + - Click `Add Secret` + +2. Add Azure DevOps personal access token, project, and org to the CODESPACES **Secrets** tab. + - Navigate to the `Settings` tab in your repo + - Find `Secrets` and click the down arrow + - Click `Codespaces` + - Click `New Codespaces Secret` to create a new secret. + - Name the secret `AZDO_TOKEN` + - Paste in the Azure DevOps PAT generated previously + - Click `Add Secret` + - Click `New Codespaces Secret` to create another secret. + - Name the secret `AZDO_PROJECT` + - Type in the Azure DevOps project name. This should be `ValetBootstrap` + - Click `Add Secret` + - Click `New Codespaces Secret` to create a new secret. + - Name the secret `AZDO_ORG` + - Type in the Azure DevOps organization name + - Click `Add Secret` + +3. Run the Actions workflow + - CLick the `Actions` tab + - Select the `Valet Bootstrap for Azure DevOps` action + - Click `Run Workflow` + - Input the Azure DevOps Organization name identified above + - Input the Azure DevOps user name of the user that created the Azure DevOps PAT above. This will be an email address + - Accept the default Azure DevOps project name or change it to one of your preference + - Click `Run Workflow` + - Verify the workflow completed successfully + +### Example ### +![runaction](https://user-images.githubusercontent.com/26442605/167679930-9bdf6f4f-2e94-4145-aed3-8ee3e8e91d90.png) + + +## Use Valet with a codespace + +1. Start the codespace + - Click the `Code` button above repository + - Click the `Codespaces` tab + - Click `New Codespace` + - Wait a couple minutes, then verify that the codespace starts up. Once it is fully booted up, the termininal should be present. +2. Run Valet + - Verify you are in the Visual Studio Code terminal + - Change to the Valet directory by typing `cd scripts` + - Run the valet command by typing `valet`. Verify that Valet details all commands. + - Start using Valet + +## Labs for Azure DevOps +Perform the following labs to test-drive Valet +- [Audit Azure DevOps pipelines using the Valet audit command](valet-audit-lab.md) +- [Dry run the migration of an Azure DevOps pipeline to GitHub Actions](valet-dry-run-lab.md) +- [Migrate an Azure DevOps pipeline to GitHub Actions](valet-migrate-lab.md) +- [Migrate an Azure DevOps pipeline to GitHub Actions with a custom transformer](valet-migrate-custom-lab.md) +- [Forecast: Valet forecast lab](valet-forecast-lab.md) diff --git a/azure_devops/valet-audit-lab.md b/azure_devops/valet-audit-lab.md new file mode 100644 index 0000000..59f127a --- /dev/null +++ b/azure_devops/valet-audit-lab.md @@ -0,0 +1,44 @@ +# Audit Azure DevOps pipelines using the Valet audit command +In this lab, you will use Valet to audit Azure DevOps pipelines in an Azure DevOps project. + +## Prerequisites + +1. Follow all steps [here](/labs/azure_devops#readme) to set up your environment +2. Create or start a codespace in this repository (if not started) + +## Perform an audit +You will use the codespace preconfigured in this repository to perform the audit. + +1. Navigate to the codespace Visual Studio Code terminal +2. Verify you are in the scripts directory +3. Now, from the `./scripts` folder in your repository, run Valet to verify your Azure DevOps configuration: + +``` +cd scripts +valet audit azure-devops --output-dir . +``` +### Example +![runaudit](https://user-images.githubusercontent.com/26442605/160930617-d4d2f4a8-7b39-47d6-ab2c-60868cb56e5f.png) + +4. Valet displays green log files to indicate a successful audit + +### Example +![audit-output](https://user-images.githubusercontent.com/26442605/161104845-3d9d7493-794f-4787-9a89-3dd3c15a8a8d.png) + +## View audit output +The audit summary, logs, Azure DevOps yml, and GitHub yml should all be located in the scripts folder. + +1. Under the `scripts` folder find the `audit_summary.md` +2. Right-click the `auditsummary.md` file and select `Open Preview` +3. The file contains the audit summary details about what can and can't be migrated to GitHub Actions. +4. Review the file. + +### Example +![audit-summary](https://user-images.githubusercontent.com/26442605/161105335-4c38ea73-b5a5-4edc-9d89-d6febcae46d4.png) + +## Review the pipelines +The `audit` command grabs the yml, classic, and release pipelines from Azure DevOps and converts them to GitHub Actions. + +### Example +View the source yml and the proposed GitHub yml +![audit-pipelines](https://user-images.githubusercontent.com/26442605/161105649-dd20235d-bb98-4949-baa3-dac561427257.png) diff --git a/azure_devops/valet-dry-run-lab.md b/azure_devops/valet-dry-run-lab.md new file mode 100644 index 0000000..1303a0f --- /dev/null +++ b/azure_devops/valet-dry-run-lab.md @@ -0,0 +1,49 @@ +# Dry run the migration of an Azure DevOps pipeline to GitHub Actions +In this lab, you will use the `valet dry-run` command on one Azure DevOps pipeline. + +## Prerequisites + +1. Follow all steps [here](/labs/azure_devops#readme) to set up your environment +2. Create or start a codespace in this repository (if not started) +3. You have completed the [Valet audit lab](valet-audit-lab.md). + +## Identify the Azure DevOps pipeline ID to use +You will need a pipeline ID to perform the dry run +1. Go to the `scripts/ValetBootstrap/pipelines` folder +2. Open the `scripts/ValetBootstrap/pipelines/valet-mapper-example.config.json` file +3. Look for the `web - href` link +4. At the end of the link is the pipeline ID. Copy or note the ID. + +### Example +![configpipelineid](https://user-images.githubusercontent.com/26442605/161106098-3b9b05ec-ee5d-4b21-ab07-9f05f8cf1d98.png) + + +## Perform a dry run +You will use the codespace preconfigured in this repository to perform the dry run. + +1. Navigate to the codespace Visual Studio Code terminal +2. Verify you are in the scripts directory +3. Copy the following command and replace: + - `GITHUB-ORG` with the name of your organization. + - `GITHUB-REPO` with the name of your repository. + - `PIPELINE-ID` with your pipeline ID. + +``` +cd scripts +valet dry-run azure-devops pipeline --target-url https://github.com/GITHUB-ORG/GITHUB-REPO --pipeline-id PIPELINE-ID --output-dir .dry-runs +``` +4. Now, from the `./scripts` folder in your repository, run `valet dry-run` to see the output: + +### Example +![dryrun-ex2](https://user-images.githubusercontent.com/26442605/161107259-39076729-2ac8-4104-8170-11061b732593.png) + +4. Valet will create a folder called `dry-runs` under the scripts folder that shows what will be migrated. + +### Example +![dryrun-output](https://user-images.githubusercontent.com/26442605/161106810-6a48b261-8099-449b-a41c-3d1e0903485a.png) + +## View dry-run output +The dry-run output will show you the GitHub Actions yml that will be migrated to GitHub. + +### Example +![dryrunyml](https://user-images.githubusercontent.com/26442605/161108244-28da94d6-c28d-4484-bc08-cb3392d7745e.png) diff --git a/azure_devops/valet-forecast-lab.md b/azure_devops/valet-forecast-lab.md new file mode 100644 index 0000000..fd7bb86 --- /dev/null +++ b/azure_devops/valet-forecast-lab.md @@ -0,0 +1,3 @@ +# Forecast Azure DevOps to GitHub using Valet forecast command + +### Coming soon diff --git a/azure_devops/valet-migrate-custom-lab.md b/azure_devops/valet-migrate-custom-lab.md new file mode 100644 index 0000000..675eeb5 --- /dev/null +++ b/azure_devops/valet-migrate-custom-lab.md @@ -0,0 +1,88 @@ +# Migrate an Azure DevOps pipeline to GitHub Actions with a custom transformer +In this lab, you will create a custom plugin that transforms some of the existing migration mapping and replaces it with your own mapping. + +## Prerequisites + +1. Follow all steps [here](/labs/azure_devops#readme) to set up your environment +2. Create or start a codespace in this repository (if not started) +3. Complete the [Valet audit lab](valet-audit-lab.md). +4. Complete the [Valet migrate lab](valet-migrate-lab.md). + +## Identify the Azure DevOps pipeline ID to use +You will need the `valet-mapper-example` Azure DevOps pipeline ID to perform the migration +1. Go to the `scripts/ValetBootstrap/pipelines` folder +2. Open the `scripts/ValetBootstrap/pipelines/valet-mapper-example.config.json` file +3. Look for the `web - href` link +4. At the end of the link is the pipeline ID. Copy or note the ID. + +### Example +![configpipelineid](https://user-images.githubusercontent.com/26442605/161106098-3b9b05ec-ee5d-4b21-ab07-9f05f8cf1d98.png) + +## Create a custom transformer +To create a transformer, you need to create a Ruby file that looks as follows: +``` ruby +transform "azuredevopstaskname" do |item| + # your ruby code here that produces output + end +``` + +We start by changing the function name to match the Azure DevOps task name `DotNetCoreCLI@2`. +The way you find this name is by clicking the **view yaml** button at a task in the pipeline: + +This results in the following code: +``` ruby +transform "DotNetCoreCLI@2" do |item| + # your ruby code here that produces output + end +``` +The parameter item is a collection of items than contain the properties of the original task that was retrieved from Azure DevOps. +In this case we can see in the yaml that the properties that are set are `command` and `projects`. + +This is what you can expect to find when we would dump the information. To determine what is in the item being passed, you can do the following: +``` ruby +transform "DotNetCoreCLI@2" do |item| + puts item + end +``` + +Add the following code to the ruby file: +``` Ruby +transform "DotNetCoreCLI@2" do |item| + projects = item["projects"] + command = item['command'] + run_command = [] + + if(projects.include?("$")) + if(command.nil?) + command = "build" + end + run_command << "shopt -s globstar; for f in ./**/*.csproj; do dotnet #{command} $f #{item['arguments'] } ; done" + else + run_command << "dotnet #{command} #{item['projects']} #{item['arguments'] }" + end + { + shell: "bash", + run: run_command.join("\n") + } +end +``` +### Example +![mapper-ex1](https://user-images.githubusercontent.com/26442605/161116232-c3dab5ba-8ca5-4dd0-a659-b871646ab82f.png) + +Run the `migrate` command with the transformer again and pass it the custom plugin. Look at the result and see if it results in a successful build. + +``` +cd scripts +valet migrate azure-devops pipeline --target-url https://github.com/GITHUB-ORG/GITHUB-REPO --pipeline-id PIPELINE-ID --custom-transformers plugin/DotNetCoreCLI.rb +``` +Now, from the `./scripts` folder in your repository, run `valet migrate` with the custom transformer to migrate the pipeline to GitHub Actions: + +### Example +![mapper-ex2](https://user-images.githubusercontent.com/26442605/161116637-15c01950-ede0-4992-876b-6a3fe5688723.png) + +## View the pull request +The migrate output will show you the pull request on GitHub. Note here that the checks on the pull request all passed! + +### Example +![mapper-ex3](https://user-images.githubusercontent.com/26442605/161117488-93e38847-3034-4f04-a768-e74e16dba4ae.png) + diff --git a/azure_devops/valet-migrate-lab.md b/azure_devops/valet-migrate-lab.md new file mode 100644 index 0000000..8ff2dcc --- /dev/null +++ b/azure_devops/valet-migrate-lab.md @@ -0,0 +1,49 @@ +# Migrate an Azure DevOps pipeline to GitHub Actions +In this lab, you will use the Valet `migrate` command to migrate an Azure DevOps pipeline to GitHub Actions. + +## Prerequisites + +1. Follow all steps [here](/labs/azure_devops#readme) to set up your environment +2. Create or start a codespace in this repository (if not started) +3. Completed the [Valet audit lab](valet-audit-lab.md). + +## Identify the Azure DevOps pipeline ID to use +You will need a pipeline ID to perform the migration +1. Go to the `scripts/ValetBootstrap/pipelines` folder +2. Open the `scripts/ValetBootstrap/pipelines/valet-pipeline1.config.json` file +3. Look for the `web - href` link +4. At the end of the link is the pipeline ID. Copy or note the ID. + +### Example +![Screen Shot 2022-05-10 at 8 50 06 AM](https://user-images.githubusercontent.com/26442605/167670536-b46aa383-74bd-4e22-a782-0de5d0ce64a5.png) + + +## Perform a migration +You will use the codespace preconfigured in this repository to perform the migration. + +1. Navigate to the codespace Visual Studio Code terminal +2. Verify you are in the scripts directory +3. Copy the following command and replace: + - `GITHUB-ORG` with the name of your organization. + - `GITHUB-REPO` with the name of your repository. + - `PIPELINE-ID` with your pipeline ID. +4. Now, from the `./scripts` folder in your repository, run `valet migrate` to migrate the pipeline to GitHub Actions. +``` +cd scripts +valet migrate azure-devops pipeline --target-url https://github.com/GITHUB-ORG/GITHUB-REPO --pipeline-id PIPELINE-ID +``` + +### Example +![migrate-command](https://user-images.githubusercontent.com/26442605/161110277-45d9fff0-9d45-4946-a2a7-8f82fbb5d43f.png) + +5. Valet will create a pull request directly to your GitHub repository. +6. Click the green pull request link in the output of the migrate command. See below. + +### Example +![migrateoutput](https://user-images.githubusercontent.com/26442605/167672012-0580a215-29d4-4aff-a730-3e769414b1b7.png) + +## View the pull request +The migrate output will show you the pull request on GitHub. + +### Example +![migrate-pr](https://user-images.githubusercontent.com/26442605/161110724-f39d9cb9-1992-44c5-bea5-da2fcebb074c.png) diff --git a/code/Bootcamp.sln b/code/Bootcamp.sln new file mode 100644 index 0000000..099b74f --- /dev/null +++ b/code/Bootcamp.sln @@ -0,0 +1,56 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30114.105 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B26D43AA-4A35-4035-9E99-48EF9A3E64DD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Attendee", "src\Attendee\Attendee.csproj", "{2804EC63-670C-4970-85E4-2A63C9327FF8}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{348A52EC-7046-4D1A-88DB-55B025C2BB68}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AttendeeTest", "test\AttendeeTest\AttendeeTest.csproj", "{DED76823-F195-46D4-8509-5692E3431D53}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2804EC63-670C-4970-85E4-2A63C9327FF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2804EC63-670C-4970-85E4-2A63C9327FF8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2804EC63-670C-4970-85E4-2A63C9327FF8}.Debug|x64.ActiveCfg = Debug|Any CPU + {2804EC63-670C-4970-85E4-2A63C9327FF8}.Debug|x64.Build.0 = Debug|Any CPU + {2804EC63-670C-4970-85E4-2A63C9327FF8}.Debug|x86.ActiveCfg = Debug|Any CPU + {2804EC63-670C-4970-85E4-2A63C9327FF8}.Debug|x86.Build.0 = Debug|Any CPU + {2804EC63-670C-4970-85E4-2A63C9327FF8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2804EC63-670C-4970-85E4-2A63C9327FF8}.Release|Any CPU.Build.0 = Release|Any CPU + {2804EC63-670C-4970-85E4-2A63C9327FF8}.Release|x64.ActiveCfg = Release|Any CPU + {2804EC63-670C-4970-85E4-2A63C9327FF8}.Release|x64.Build.0 = Release|Any CPU + {2804EC63-670C-4970-85E4-2A63C9327FF8}.Release|x86.ActiveCfg = Release|Any CPU + {2804EC63-670C-4970-85E4-2A63C9327FF8}.Release|x86.Build.0 = Release|Any CPU + {DED76823-F195-46D4-8509-5692E3431D53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DED76823-F195-46D4-8509-5692E3431D53}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DED76823-F195-46D4-8509-5692E3431D53}.Debug|x64.ActiveCfg = Debug|Any CPU + {DED76823-F195-46D4-8509-5692E3431D53}.Debug|x64.Build.0 = Debug|Any CPU + {DED76823-F195-46D4-8509-5692E3431D53}.Debug|x86.ActiveCfg = Debug|Any CPU + {DED76823-F195-46D4-8509-5692E3431D53}.Debug|x86.Build.0 = Debug|Any CPU + {DED76823-F195-46D4-8509-5692E3431D53}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DED76823-F195-46D4-8509-5692E3431D53}.Release|Any CPU.Build.0 = Release|Any CPU + {DED76823-F195-46D4-8509-5692E3431D53}.Release|x64.ActiveCfg = Release|Any CPU + {DED76823-F195-46D4-8509-5692E3431D53}.Release|x64.Build.0 = Release|Any CPU + {DED76823-F195-46D4-8509-5692E3431D53}.Release|x86.ActiveCfg = Release|Any CPU + {DED76823-F195-46D4-8509-5692E3431D53}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {2804EC63-670C-4970-85E4-2A63C9327FF8} = {B26D43AA-4A35-4035-9E99-48EF9A3E64DD} + {DED76823-F195-46D4-8509-5692E3431D53} = {348A52EC-7046-4D1A-88DB-55B025C2BB68} + EndGlobalSection +EndGlobal diff --git a/code/readme.md b/code/readme.md new file mode 100644 index 0000000..d58f7e7 --- /dev/null +++ b/code/readme.md @@ -0,0 +1,5 @@ +# code folder +This folder contains a dotnet core application used for building puproses with the CI/CD selected. + +### Note any file added to this folder or sub folders will get migrated to the Azure DevOps instance when the GitHub Action runs to create and bootstrap the Azure DevOps project + diff --git a/code/src/Attendee/Attendee.cs b/code/src/Attendee/Attendee.cs new file mode 100644 index 0000000..37e4c52 --- /dev/null +++ b/code/src/Attendee/Attendee.cs @@ -0,0 +1,15 @@ +using System; + +namespace Attendees +{ + public class Attendee + { + public bool AddAttendee(string added) + { + if (added == "exists") + return true; + + return false; + } + } +} diff --git a/code/src/Attendee/Attendee.csproj b/code/src/Attendee/Attendee.csproj new file mode 100644 index 0000000..563e6f9 --- /dev/null +++ b/code/src/Attendee/Attendee.csproj @@ -0,0 +1,7 @@ + + + + net5.0 + + + diff --git a/code/test/AttendeeTest/AttendeeExists.cs b/code/test/AttendeeTest/AttendeeExists.cs new file mode 100644 index 0000000..70e3b6d --- /dev/null +++ b/code/test/AttendeeTest/AttendeeExists.cs @@ -0,0 +1,18 @@ +using System; +using Xunit; +using Xunit.Extensions; +using Attendees; + +namespace AttendeeTest +{ + public class AttendeeTest + { + [Fact] + public void AttendeeExistsReturnTrue() + { + Attendee attendee = new Attendee(); + bool doesExist = attendee.AddAttendee("doesnotexist"); + Assert.False(doesExist, "The attendee does not exist"); + } + } +} diff --git a/code/test/AttendeeTest/AttendeeTest.csproj b/code/test/AttendeeTest/AttendeeTest.csproj new file mode 100644 index 0000000..8b41439 --- /dev/null +++ b/code/test/AttendeeTest/AttendeeTest.csproj @@ -0,0 +1,26 @@ + + + + net5.0 + + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/jenkins/readme.md b/jenkins/readme.md new file mode 100644 index 0000000..8349c4a --- /dev/null +++ b/jenkins/readme.md @@ -0,0 +1 @@ +# Coming Soon! diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..d5069b2 --- /dev/null +++ b/readme.md @@ -0,0 +1,16 @@ +# Welcome to Valet labs! +These Valet labs let you test-drive Valet by bootstrapping the environment of your choosing. Below are the specific functions of the labs. + +## Bootstrap your environment +The first step toward setting up a bootstrapped environment is to choose what platform to run Valet against. Currently these labs support Azure DevOps. The default page of the lab of your choosing will detail how to configure and run the action to bootstrap the environment. + +## Configure and run Codespaces +After you have an environment bootstrapped, you run Valet via Codespaces. The codespace has docker running and will update to the latest Valet environment. + +## Labs +Once you have a bootstrapped environment and Valet running via Codespaces, you can proceed to the labs. + +## Environments to bootstrap +- [Azure DevOps](azure_devops) +- [Jenkins](jenkins) + diff --git a/valet/.env.local b/valet/.env.local new file mode 100644 index 0000000..0c10345 --- /dev/null +++ b/valet/.env.local @@ -0,0 +1,6 @@ +GITHUB_ACCESS_TOKEN= +GITHUB_INSTANCE_URL= + +AZURE_DEVOPS_PROJECT= +AZURE_DEVOPS_ORGANIZATION= +AZURE_DEVOPS_INSTANCE_URL= diff --git a/valet/valet b/valet/valet new file mode 100644 index 0000000..025b8cf --- /dev/null +++ b/valet/valet @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +# Version 1.1.1 + +VALET_REGISTRY=${VALET_REGISTRY:="ghcr.io"} +VALET_IMAGE=${VALET_IMAGE:-"$VALET_REGISTRY/valet-customers/valet-cli"} +VALET_IMAGE_VERSION=${VALET_IMAGE_VERSION:-"latest"} + +VALET_TOKEN_FILE=${VALET_TOKEN_FILE:-".env.local"} +VALET_ENV_VARS=('GITHUB_ACCESS_TOKEN' 'AZURE_DEVOPS_ACCESS_TOKEN' 'GITHUB_INSTANCE_URL' 'JENKINSFILE_ACCESS_TOKEN' 'JENKINS_USERNAME' 'JENKINS_ACCESS_TOKEN' 'JENKINS_INSTANCE_URL' 'TRAVIS_CI_ACCESS_TOKEN' 'TRAVIS_CI_INSTANCE_URL' 'TRAVIS_CI_SOURCE_GITHUB_ACCESS_TOKEN' 'TRAVIS_CI_SOURCE_GITHUB_INSTANCE_URL' 'YAML_VERBOSITY' 'HTTP_PROXY' 'HTTPS_PROXY' 'NO_PROXY' 'OCTOKIT_PROXY' 'OCTOKIT_SSL_VERIFY_MODE') +VALET_LOCAL_FOLDER=${VALET_LOCAL_FOLDER:-$(pwd)} + +if [[ -z "${DOCKER_OPTIONS+x}" ]]; then + DOCKER_OPTIONS="-t" +fi + +if [[ -e "$VALET_TOKEN_FILE" ]]; then + dockerArgs="--env-file $VALET_TOKEN_FILE" +fi + +for varName in ${VALET_ENV_VARS[*]}; do + if [ "${!varName}" != "" ]; then + dockerArgs=$dockerArgs" --env $varName" + fi +done + +MSYS_NO_PATHCONV=1 docker run --rm $dockerArgs $DOCKER_OPTIONS -v "$VALET_LOCAL_FOLDER"":/data" "$VALET_IMAGE":"$VALET_IMAGE_VERSION" "$@" diff --git a/valet/valet-update b/valet/valet-update new file mode 100644 index 0000000..2467924 --- /dev/null +++ b/valet/valet-update @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +# Version 1.1.0 + +VALET_REGISTRY=${VALET_REGISTRY:="ghcr.io"} +VALET_IMAGE=${VALET_IMAGE:-"$VALET_REGISTRY/valet-customers/valet-cli"} + +docker login $VALET_REGISTRY + +docker pull $VALET_IMAGE:latest