From 5699688adbfed3e4794d187923d1e9358bc49c90 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Wed, 28 Sep 2022 22:18:56 +0200 Subject: [PATCH 1/9] fix: use path.SEP for parsing platform module ids fix cross-platform issues --- src/commands/foundation/PlatformModuleType.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/foundation/PlatformModuleType.ts b/src/commands/foundation/PlatformModuleType.ts index f0967a97..2cd46b02 100644 --- a/src/commands/foundation/PlatformModuleType.ts +++ b/src/commands/foundation/PlatformModuleType.ts @@ -27,7 +27,7 @@ export class PlatformModuleType extends StringType { } static parseModuleId(matchedPath: string) { - const components = matchedPath.split("/"); + const components = matchedPath.split(path.SEP); const platformIndex = components.lastIndexOf("platforms"); const dropTerragruntHclComponent = -1; From 8cf229ad83b6418af24f79bd6d8d12d8c2518802 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Thu, 29 Sep 2022 09:21:54 +0200 Subject: [PATCH 2/9] chore: simplify windows install script - simplify remote install script - use powersehll to set environment variable in current session and permanently, don't write to registry. --- .github/README.md | 10 +++++----- install.ps1 | 14 ++++++++------ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/.github/README.md b/.github/README.md index 9b5b7628..73ac20d5 100644 --- a/.github/README.md +++ b/.github/README.md @@ -78,21 +78,21 @@ You can install `collie` using our install scripts below **Linux / Ubuntu** -``` +```sh curl -sf -L https://raw.githubusercontent.com/meshcloud/collie-cli/main/install.sh | sudo bash ``` **Mac OS X** -``` +```sh curl -sf -L https://raw.githubusercontent.com/meshcloud/collie-cli/main/install.sh | sh ``` **Windows** -Simply copy the content of -[`install.ps1`](https://github.com/meshcloud/collie-cli/blob/develop/install.ps1) -and run it in your PowerShell console. +```powershell +irm https://raw.githubusercontent.com/meshcloud/collie-cli/main/install.ps1 | iex +``` ### 🚀 Connecting to your clouds diff --git a/install.ps1 b/install.ps1 index d0e8b39d..b63f52ee 100644 --- a/install.ps1 +++ b/install.ps1 @@ -42,12 +42,14 @@ catch { # Ask user whether to add Collie to the environment variables automatically $userenv = $(Write-Host "Adding Collie to your Environment-Variables? (y/n)" -NoNewLine -ForegroundColor Green; Read-Host) if ($userenv -like "y") { - $Reg = "HKCU:Environment" - $OldPath = (Get-ItemProperty -Path $Reg -Name PATH).Path - $NewPath = $OldPath + ";" + $($folder.FullName).ToString() - Set-ItemProperty -Path $Reg -Name PATH -Value $NewPath - Write-Host "Reloading Powershell is required!`n" -ForegroundColor Yellow + $BinDir = $($folder.FullName).ToString() + $User = [EnvironmentVariableTarget]::User + $Path = [Environment]::GetEnvironmentVariable('Path', $User) + if (!(";$Path;".ToLower() -like "*;$BinDir;*".ToLower())) { + [Environment]::SetEnvironmentVariable('Path', "$Path;$BinDir", $User) + $Env:Path += ";$BinDir" + } } Write-Host "[OK] Collie CLI successfully installed: '$($folder.FullName)'`n" -ForegroundColor Green -# Done \ No newline at end of file +Write-Output "Run 'collie --help' to get started" \ No newline at end of file From 83c41558fcec655a98c66f3b008fc351535037db Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Thu, 29 Sep 2022 09:47:14 +0200 Subject: [PATCH 3/9] chore: fix deno task run on windows correctly handle building source map path on windows --- flags.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/flags.ts b/flags.ts index d2ec46ff..698fd2ba 100644 --- a/flags.ts +++ b/flags.ts @@ -1,5 +1,9 @@ import { FLAGS } from "./src/info.ts"; +import { isWindows } from "./src/os.ts"; -const __dirname = new URL(".", import.meta.url).pathname; +let __dirname = new URL(".", import.meta.url).pathname; +if (isWindows) { + __dirname = __dirname.substring(1); // on windows we have to strip the path so it looks like C:/... instead of /C:/... +} console.log(FLAGS + ` --import-map=${__dirname}src/import_map.json`); From 701dab133a4ceb6a4e8c93c06c8cb6ca247c9b25 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Thu, 29 Sep 2022 09:49:28 +0200 Subject: [PATCH 4/9] fix: invoke commands through shell on windows this fixes "program not found" errors on windows when collie tries to invoke a cli command --- src/process/QuietProcessRunner.ts | 3 ++- src/process/ShellRunnerPolicy.ts | 14 ++++++++++++++ src/process/TransparentProcessRunner.ts | 3 ++- 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 src/process/ShellRunnerPolicy.ts diff --git a/src/process/QuietProcessRunner.ts b/src/process/QuietProcessRunner.ts index 39814f8f..0484ce78 100644 --- a/src/process/QuietProcessRunner.ts +++ b/src/process/QuietProcessRunner.ts @@ -1,6 +1,7 @@ import { ProcessRunnerOptions } from "./ProcessRunnerOptions.ts"; import { IProcessRunner } from "./IProcessRunner.ts"; import { ProcessResultWithOutput } from "./ProcessRunnerResult.ts"; +import { ShellRunnerPolicy } from "./ShellRunnerPolicy.ts"; /** * Runs a subprocess quietly by buffering its stdout and stderr in memory until completion. @@ -13,7 +14,7 @@ export class QuietProcessRunner ): Promise { const p = Deno.run({ ...options, - cmd: commands, + cmd: ShellRunnerPolicy.shellCommands(commands), stdout: "piped", stderr: "piped", }); diff --git a/src/process/ShellRunnerPolicy.ts b/src/process/ShellRunnerPolicy.ts new file mode 100644 index 00000000..1cb9feb9 --- /dev/null +++ b/src/process/ShellRunnerPolicy.ts @@ -0,0 +1,14 @@ +import { isWindows } from "../os.ts"; + +export class ShellRunnerPolicy { + static shellCommands(commands: string[]) { + // on windows, we need run through the user's shell as otherwise we have to run e.g. az.exe instead of az + if (isWindows) { + return ["cmd.exe", "/c", ...commands]; + } + + // on unix, don't run through the user's shell as that will incur cost of running shell setup (e.g. .bashrc) + // for every new process that we spawn, and collie typcially spawns many + return commands; + } +} diff --git a/src/process/TransparentProcessRunner.ts b/src/process/TransparentProcessRunner.ts index e1cad1f0..adba2a1e 100644 --- a/src/process/TransparentProcessRunner.ts +++ b/src/process/TransparentProcessRunner.ts @@ -1,6 +1,7 @@ import { ProcessResult } from "./ProcessRunnerResult.ts"; import { ProcessRunnerOptions } from "./ProcessRunnerOptions.ts"; import { IProcessRunner } from "./IProcessRunner.ts"; +import { ShellRunnerPolicy } from "./ShellRunnerPolicy.ts"; /** * Runs a subprocess transaprently by connecting it to collie's stdout/stderr. @@ -13,7 +14,7 @@ export class TransparentProcessRunner implements IProcessRunner { ): Promise { const p = Deno.run({ ...options, - cmd: commands, + cmd: ShellRunnerPolicy.shellCommands(commands), stdout: "inherit", stderr: "inherit", }); From 9eff1038efec3a1110e97b4a40bc603a357efcef Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Thu, 29 Sep 2022 10:37:35 +0200 Subject: [PATCH 5/9] fix: relax git version parsing for custom git builds many distros ship custom git builds that return distro-sepcific build info in "git --version" output --- src/api/git/GitCliDetector.test.ts | 20 ++++++++++++++++++++ src/api/git/GitCliDetector.ts | 10 ++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 src/api/git/GitCliDetector.test.ts diff --git a/src/api/git/GitCliDetector.test.ts b/src/api/git/GitCliDetector.test.ts new file mode 100644 index 00000000..28160828 --- /dev/null +++ b/src/api/git/GitCliDetector.test.ts @@ -0,0 +1,20 @@ +import { GitCliDetector } from "./GitCliDetector.ts"; +import { StubProcessRunner } from "../../process/StubProcessRunner.ts"; +import { assertEquals } from "std/testing/assert"; + +Deno.test( + "can parse version numbers", + () => { + const sut = new GitCliDetector(new StubProcessRunner()); + + const tests = [ + ["git version 2.19.0", "2.19.0"], + ["git version 2.19.0.windows.1", "2.19.0"], + ]; + + tests.forEach(([output, expected]) => { + const actual = sut.parseVersion(output); + assertEquals(actual, expected); + }); + }, +); diff --git a/src/api/git/GitCliDetector.ts b/src/api/git/GitCliDetector.ts index b18590e9..744aff0a 100644 --- a/src/api/git/GitCliDetector.ts +++ b/src/api/git/GitCliDetector.ts @@ -7,16 +7,18 @@ export class GitCliDetector extends CliDetector { super("git", runner); } - protected parseVersion(versionCmdOutput: string): string { - const components = versionCmdOutput.split(" "); + public parseVersion(versionCmdOutput: string): string { + // some git version strings have additional build info in them, so we only extract what looks like a version number + const versionRegex = /\d+.\d+.\d+/g; - const version = components[0].substring("git version ".length); + const matches = versionCmdOutput.match(versionRegex); - return version; + return (matches && matches[0]) || ""; } protected isSupportedVersion(version: string): boolean { // a simple lexicographic comparison is sufficient for our needs + return version > "2.0.0"; } } From 1c346dec5590c5dc69247008f4988d2875316a4c Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Thu, 29 Sep 2022 14:08:32 +0200 Subject: [PATCH 6/9] fix: make select prompts feature usage instructions on windows up and down arrows don't work, see https://github.com/c4spar/deno-cliffy/issues/272 users can get stuck without on-screen instructions so we now always provide them --- src/api/aws/AwsPlatformSetup.ts | 6 ++++-- src/api/az/AzPlatformSetup.ts | 3 ++- src/api/gcloud/GcloudPlatformSetup.ts | 5 +++-- src/commands/foundation/new.command.ts | 2 ++ src/commands/interactive/interactive.command.ts | 4 +++- src/commands/kit/apply.command.ts | 6 ++++-- 6 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/api/aws/AwsPlatformSetup.ts b/src/api/aws/AwsPlatformSetup.ts index 718cf13b..3a2c91d9 100644 --- a/src/api/aws/AwsPlatformSetup.ts +++ b/src/api/aws/AwsPlatformSetup.ts @@ -5,6 +5,7 @@ import { MarkdownDocument } from "../../model/MarkdownDocument.ts"; import { Dir } from "../../cli/DirectoryGenerator.ts"; import { CLI } from "../../info.ts"; import { PlatformSetup } from "../PlatformSetup.ts"; +import { isWindows } from "../../os.ts"; export class AwsPlatformSetup extends PlatformSetup { constructor(private readonly aws: AwsCliFacade) { @@ -22,7 +23,8 @@ export class AwsPlatformSetup extends PlatformSetup { const profile = await Select.prompt({ message: "Select an AWS CLI Profile", options: profiles, - search: true, + search: !isWindows, // see https://github.com/c4spar/deno-cliffy/issues/272#issuecomment-1262197264, + info: true }); this.progress("trying to sign in and get account info"); @@ -54,7 +56,7 @@ export class AwsPlatformSetup extends PlatformSetup { message: `Choose the default AWS region for collie commands`, default: region, options: regions.Regions.map((x) => x.RegionName), - search: true, + search: !isWindows, // see https://github.com/c4spar/deno-cliffy/issues/272#issuecomment-1262197264 info: true, }); diff --git a/src/api/az/AzPlatformSetup.ts b/src/api/az/AzPlatformSetup.ts index 9c201c0c..cccc88eb 100644 --- a/src/api/az/AzPlatformSetup.ts +++ b/src/api/az/AzPlatformSetup.ts @@ -5,6 +5,7 @@ import { MarkdownDocument } from "../../model/MarkdownDocument.ts"; import { Dir } from "../../cli/DirectoryGenerator.ts"; import { PlatformSetup } from "../PlatformSetup.ts"; import { MeshError } from "../../errors.ts"; +import { isWindows } from "../../os.ts"; export class AzPlatformSetup extends PlatformSetup { constructor(private readonly az: AzCliFacade) { @@ -27,7 +28,7 @@ export class AzPlatformSetup extends PlatformSetup { name: x.name + " / AAD " + x.tenantId, value: x.id, })), - search: true, + search: !isWindows, // see https://github.com/c4spar/deno-cliffy/issues/272#issuecomment-1262197264 info: true, }); diff --git a/src/api/gcloud/GcloudPlatformSetup.ts b/src/api/gcloud/GcloudPlatformSetup.ts index abe09893..84fd190c 100644 --- a/src/api/gcloud/GcloudPlatformSetup.ts +++ b/src/api/gcloud/GcloudPlatformSetup.ts @@ -6,6 +6,7 @@ import { PlatformSetup } from "../PlatformSetup.ts"; import { GcloudCliFacade } from "./GcloudCliFacade.ts"; import { MeshError } from "../../errors.ts"; import { organizationId } from "./Model.ts"; +import { isWindows } from "../../os.ts"; export class GcloudPlatformSetup extends PlatformSetup { constructor(private readonly gcloud: GcloudCliFacade) { @@ -23,7 +24,7 @@ export class GcloudPlatformSetup extends PlatformSetup { const configurationName = await Select.prompt({ message: "Select a gcloud CLI configuration", options: configurations.map((x) => x.name), - search: true, + search: !isWindows, // see https://github.com/c4spar/deno-cliffy/issues/272#issuecomment-1262197264 info: true, }); @@ -46,7 +47,7 @@ export class GcloudPlatformSetup extends PlatformSetup { name: x.displayName, value: x.name, })), - search: true, + search: !isWindows, // see https://github.com/c4spar/deno-cliffy/issues/272#issuecomment-1262197264, info: true, }); diff --git a/src/commands/foundation/new.command.ts b/src/commands/foundation/new.command.ts index b635fe22..e3260291 100644 --- a/src/commands/foundation/new.command.ts +++ b/src/commands/foundation/new.command.ts @@ -82,6 +82,7 @@ async function promptPlatformEntries( name: "action", message: "Select an action to continue", type: Select, + info: true, options: [ { value: "add", name: `${colors.green("+")} add cloud platform` }, { value: "done", name: `${colors.green("✔")} save & exit` }, @@ -109,6 +110,7 @@ async function promptPlatformEntries( name: "cloud", message: "What type of cloud do you want to add", type: Select, + info: true, options: [ { value: "aws", name: "AWS" }, { value: "azure", name: "Azure" }, diff --git a/src/commands/interactive/interactive.command.ts b/src/commands/interactive/interactive.command.ts index cebdcea3..7c01da24 100644 --- a/src/commands/interactive/interactive.command.ts +++ b/src/commands/interactive/interactive.command.ts @@ -10,6 +10,8 @@ import { CollieRepository } from "../../model/CollieRepository.ts"; import { InteractivePrompts } from "./InteractivePrompts.ts"; import { prepareTenantCommand } from "../tenant/prepareTenantCommand.ts"; import { detailViewTenant } from "./detailViewTenant.ts"; +import { TopLevelCommand } from "../TopLevelCommand.ts"; +import { isWindows } from "../../os.ts"; export function registerInteractiveCommand(program: Command) { program @@ -65,7 +67,7 @@ export async function startInteractiveMode(options: GlobalCommandOptions) { name: `${x.platformTenantName} (${x.platformId} ${x.platformTenantId})`, })), - search: true, + search: !isWindows, // see https://github.com/c4spar/deno-cliffy/issues/272#issuecomment-1262197264 info: true, }); diff --git a/src/commands/kit/apply.command.ts b/src/commands/kit/apply.command.ts index 8f89bb6e..5faa87ae 100644 --- a/src/commands/kit/apply.command.ts +++ b/src/commands/kit/apply.command.ts @@ -1,7 +1,7 @@ import * as colors from "std/fmt/colors"; import * as path from "std/path"; -import { Command, Select } from "../../deps.ts"; +import { Select } from "../../deps.ts"; import { Dir, DirectoryGenerator, @@ -16,6 +16,8 @@ import { InteractivePrompts } from "../interactive/InteractivePrompts.ts"; import { KitModuleRepository } from "../../kit/KitModuleRepository.ts"; import { CommandOptionError } from "../CommandOptionError.ts"; import { PlatformConfig } from "../../model/PlatformConfig.ts"; +import { TopLevelCommand } from "../TopLevelCommand.ts"; +import { isWindows } from "../../os.ts"; interface ApplyOptions { foundation?: string; @@ -225,6 +227,6 @@ async function selectModule(moduleRepo: KitModuleRepository) { message: "Select a kit module from your repository", options, info: true, - search: true, + search: !isWindows, // see https://github.com/c4spar/deno-cliffy/issues/272#issuecomment-1262197264 }); } From b4d18cd478fe7b81258365324b0282d971b9bbeb Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Thu, 29 Sep 2022 14:33:17 +0200 Subject: [PATCH 7/9] fix: use correct path separator in collie kit apply on windows --- src/commands/kit/apply.command.ts | 7 +++++-- src/kit/KitModuleParser.ts | 4 +++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/commands/kit/apply.command.ts b/src/commands/kit/apply.command.ts index 5faa87ae..c5d70a15 100644 --- a/src/commands/kit/apply.command.ts +++ b/src/commands/kit/apply.command.ts @@ -178,7 +178,10 @@ EOF } function generateTerragrunt(kitModulePath: string) { - const isBootstrap = kitModulePath.endsWith("/bootstrap"); + const isBootstrap = kitModulePath.endsWith(`${path.SEP}bootstrap`); + + // terragrunt needs a posix style path + const posixKitModulePath = kitModulePath.replaceAll("\\", "/") const platformIncludeBlock = `include "platform" { path = find_in_parent_folders("platform.hcl") @@ -202,7 +205,7 @@ EOF }`; const terraformBlock = `terraform { - source = "\${get_repo_root()}//${kitModulePath}" + source = "\${get_repo_root()}//${posixKitModulePath}" }`; const inputsBlock = `inputs = { diff --git a/src/kit/KitModuleParser.ts b/src/kit/KitModuleParser.ts index 68d96b6c..0908cd6e 100644 --- a/src/kit/KitModuleParser.ts +++ b/src/kit/KitModuleParser.ts @@ -80,8 +80,10 @@ export class KitModuleParser { return; } + const posixRelativeModulePath = relativeModulePath.replaceAll("\\", "/") + return { - id: relativeModulePath.substring("kit/".length), + id: posixRelativeModulePath.substring("kit/".length), kitModulePath: relativeModulePath, definitionPath: relativeReadmePath, kitModule: parsed.frontmatter, From 85c5b30943d5456fa232b6404d5d75aa2ea921cd Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Thu, 29 Sep 2022 18:32:18 +0200 Subject: [PATCH 8/9] style: fix lint and fmt errors --- src/api/aws/AwsPlatformSetup.ts | 2 +- src/commands/interactive/interactive.command.ts | 1 - src/commands/kit/apply.command.ts | 5 ++--- src/kit/KitModuleParser.ts | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/api/aws/AwsPlatformSetup.ts b/src/api/aws/AwsPlatformSetup.ts index 3a2c91d9..2f0248fc 100644 --- a/src/api/aws/AwsPlatformSetup.ts +++ b/src/api/aws/AwsPlatformSetup.ts @@ -24,7 +24,7 @@ export class AwsPlatformSetup extends PlatformSetup { message: "Select an AWS CLI Profile", options: profiles, search: !isWindows, // see https://github.com/c4spar/deno-cliffy/issues/272#issuecomment-1262197264, - info: true + info: true, }); this.progress("trying to sign in and get account info"); diff --git a/src/commands/interactive/interactive.command.ts b/src/commands/interactive/interactive.command.ts index 7c01da24..fd9b3ac7 100644 --- a/src/commands/interactive/interactive.command.ts +++ b/src/commands/interactive/interactive.command.ts @@ -10,7 +10,6 @@ import { CollieRepository } from "../../model/CollieRepository.ts"; import { InteractivePrompts } from "./InteractivePrompts.ts"; import { prepareTenantCommand } from "../tenant/prepareTenantCommand.ts"; import { detailViewTenant } from "./detailViewTenant.ts"; -import { TopLevelCommand } from "../TopLevelCommand.ts"; import { isWindows } from "../../os.ts"; export function registerInteractiveCommand(program: Command) { diff --git a/src/commands/kit/apply.command.ts b/src/commands/kit/apply.command.ts index c5d70a15..fe276727 100644 --- a/src/commands/kit/apply.command.ts +++ b/src/commands/kit/apply.command.ts @@ -1,7 +1,7 @@ import * as colors from "std/fmt/colors"; import * as path from "std/path"; -import { Select } from "../../deps.ts"; +import { Select } from "../../deps.ts"; import { Dir, DirectoryGenerator, @@ -16,7 +16,6 @@ import { InteractivePrompts } from "../interactive/InteractivePrompts.ts"; import { KitModuleRepository } from "../../kit/KitModuleRepository.ts"; import { CommandOptionError } from "../CommandOptionError.ts"; import { PlatformConfig } from "../../model/PlatformConfig.ts"; -import { TopLevelCommand } from "../TopLevelCommand.ts"; import { isWindows } from "../../os.ts"; interface ApplyOptions { @@ -181,7 +180,7 @@ function generateTerragrunt(kitModulePath: string) { const isBootstrap = kitModulePath.endsWith(`${path.SEP}bootstrap`); // terragrunt needs a posix style path - const posixKitModulePath = kitModulePath.replaceAll("\\", "/") + const posixKitModulePath = kitModulePath.replaceAll("\\", "/"); const platformIncludeBlock = `include "platform" { path = find_in_parent_folders("platform.hcl") diff --git a/src/kit/KitModuleParser.ts b/src/kit/KitModuleParser.ts index 0908cd6e..984cbe39 100644 --- a/src/kit/KitModuleParser.ts +++ b/src/kit/KitModuleParser.ts @@ -80,7 +80,7 @@ export class KitModuleParser { return; } - const posixRelativeModulePath = relativeModulePath.replaceAll("\\", "/") + const posixRelativeModulePath = relativeModulePath.replaceAll("\\", "/"); return { id: posixRelativeModulePath.substring("kit/".length), From 5022e82bd79fb41edf7ebf0cae11486573198d63 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Thu, 29 Sep 2022 18:35:26 +0200 Subject: [PATCH 9/9] fix: missing import --- src/commands/kit/apply.command.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/kit/apply.command.ts b/src/commands/kit/apply.command.ts index fe276727..e4c52fbd 100644 --- a/src/commands/kit/apply.command.ts +++ b/src/commands/kit/apply.command.ts @@ -1,7 +1,7 @@ import * as colors from "std/fmt/colors"; import * as path from "std/path"; -import { Select } from "../../deps.ts"; +import { Command, Select } from "../../deps.ts"; import { Dir, DirectoryGenerator,