diff --git a/src/api/CliApiFacadeFactory.ts b/src/api/CliApiFacadeFactory.ts index 4b2b4fd..93edd79 100644 --- a/src/api/CliApiFacadeFactory.ts +++ b/src/api/CliApiFacadeFactory.ts @@ -118,7 +118,7 @@ export class CliApiFacadeFactory { const detectorRunner = this.buildQuietLoggingProcessRunner(); const detector = new GitCliDetector(detectorRunner); - const processRunner = this.buildTransparentProcessRunner(detector); + const processRunner = this.buildQuietLoggingProcessRunner(); const resultHandler = new ProcessRunnerErrorResultHandler(detector); const quietRunner = new ResultHandlerProcessRunnerDecorator( diff --git a/src/api/git/GitCliFacade.ts b/src/api/git/GitCliFacade.ts index d740c52..3dbee31 100644 --- a/src/api/git/GitCliFacade.ts +++ b/src/api/git/GitCliFacade.ts @@ -1,10 +1,10 @@ import { IProcessRunner } from "../../process/IProcessRunner.ts"; -import { ProcessResult } from "../../process/ProcessRunnerResult.ts"; +import { ProcessResultWithOutput } from "../../process/ProcessRunnerResult.ts"; import { QuietProcessRunner } from "../../process/QuietProcessRunner.ts"; export class GitCliFacade { constructor( - private readonly processRunner: IProcessRunner, + private readonly processRunner: IProcessRunner, private readonly quietRunner: QuietProcessRunner, ) {} @@ -20,10 +20,29 @@ export class GitCliFacade { await this.processRunner.run(["git", "clone", repoUrl, destDir]); } - async pull(repoDir: string) { - await this.processRunner.run(["git", "pull"], { cwd: repoDir }); + async getLatestTag(repoDir: string): Promise { + const result = await this.processRunner.run([ + "git", + "describe", + "--tags", + "--abbrev=0", + ], { cwd: repoDir }); + return result.stdout.trim(); } + async getTags(repoDir: string): Promise { + const result = await this.processRunner.run([ + "git", + "tag", + ], { cwd: repoDir }); + return result.stdout.trim(); + } + + async checkout(repoDir: string, tagValue: string) { + await this.processRunner.run(["git", "checkout", tagValue], { + cwd: repoDir, + }); + } /** * Checks if the given dir is a .git repo dir. * This method is using a QuietProcessRunner because we typcially don't want to output repo detection logic via diff --git a/src/commands/compliance/import.command.ts b/src/commands/compliance/import.command.ts index d88e688..175fa1f 100644 --- a/src/commands/compliance/import.command.ts +++ b/src/commands/compliance/import.command.ts @@ -5,6 +5,7 @@ import { GlobalCommandOptions } from "../GlobalCommandOptions.ts"; import { TopLevelCommand } from "../TopLevelCommand.ts"; import { CliApiFacadeFactory } from "../../api/CliApiFacadeFactory.ts"; import { CollieHub } from "../../model/CollieHub.ts"; +import { CollieConfig } from "../../model/CollieConfig.ts"; interface ImportOptions { clean?: boolean; @@ -31,8 +32,8 @@ export function registerImportCmd(program: TopLevelCommand) { const factory = new CliApiFacadeFactory(logger); const git = factory.buildGit(); - - const hub = new CollieHub(git, collie); + const config = new CollieConfig(collie, logger); + const hub = new CollieHub(git, collie, logger, config); if (opts.clean) { logger.progress("cleaning local cache of collie hub"); @@ -40,7 +41,7 @@ export function registerImportCmd(program: TopLevelCommand) { } logger.progress("updating local cache of collie hub from " + hub.url); - const hubDir = await hub.updateHubClone(); + const hubDir = await hub.cloneHub(); id = id || (await promptForComplianceFrameworkId(hubDir)); diff --git a/src/commands/config/get.command.ts b/src/commands/config/get.command.ts index 760e801..96956d1 100644 --- a/src/commands/config/get.command.ts +++ b/src/commands/config/get.command.ts @@ -1,6 +1,9 @@ import { GlobalCommandOptions } from "../GlobalCommandOptions.ts"; import { TopLevelCommand } from "../TopLevelCommand.ts"; -import { CollieConfig } from "../../model/CollieConfig.ts"; +import { + CollieConfig, + CollieConfigProperties, +} from "../../model/CollieConfig.ts"; import { Logger } from "../../cli/Logger.ts"; import { CollieRepository } from "../../model/CollieRepository.ts"; import { CLI } from "../../info.ts"; @@ -18,7 +21,9 @@ export function registerGetCmd(program: TopLevelCommand) { const repo = await CollieRepository.load(); const logger = new Logger(repo, opts); const config = new CollieConfig(repo, logger); - const value = config.getProperty(property); + const value = config.getProperty( + property as keyof CollieConfigProperties, + ); console.log(value); }, ); diff --git a/src/commands/init.command.ts b/src/commands/init.command.ts index b1fb0e8..d0fcf8d 100644 --- a/src/commands/init.command.ts +++ b/src/commands/init.command.ts @@ -137,8 +137,7 @@ const gitignore = `# terraform/terragrunt caches .docs # collie caches -.collie -**.collie.json +.collie/hub **.meta.json `; diff --git a/src/commands/kit/import.command.ts b/src/commands/kit/import.command.ts index 79884b5..bd64f37 100644 --- a/src/commands/kit/import.command.ts +++ b/src/commands/kit/import.command.ts @@ -7,6 +7,7 @@ import { KitModuleRepository } from "../../kit/KitModuleRepository.ts"; import { ModelValidator } from "../../model/schemas/ModelValidator.ts"; import { InteractivePrompts } from "../../cli/InteractivePrompts.ts"; import { CollieHub } from "../../model/CollieHub.ts"; +import { CollieConfig } from "../../model/CollieConfig.ts"; interface ImportOptions { clean?: boolean; @@ -33,8 +34,8 @@ export function registerImportCmd(program: TopLevelCommand) { const factory = new CliApiFacadeFactory(logger); const git = factory.buildGit(); - - const hub = new CollieHub(git, collie); + const config = new CollieConfig(collie, logger); + const hub = new CollieHub(git, collie, logger, config); if (opts.clean) { logger.progress("cleaning local cache of hub modules"); @@ -42,7 +43,7 @@ export function registerImportCmd(program: TopLevelCommand) { } logger.progress("updating local cache of hub modules from " + hub.url); - const hubDir = await hub.updateHubClone(); + const hubDir = await hub.cloneHub(); id = id || (await promptForKitModuleId(logger, hubDir)); diff --git a/src/model/CollieConfig.ts b/src/model/CollieConfig.ts index 3d1b777..19e2824 100644 --- a/src/model/CollieConfig.ts +++ b/src/model/CollieConfig.ts @@ -5,6 +5,7 @@ import { CollieRepository } from "./CollieRepository.ts"; export interface CollieConfigProperties { foundation?: string; + colliehubVersion?: string; } export class CollieConfig { @@ -19,8 +20,8 @@ export class CollieConfig { private configFilePath: string; private properties: CollieConfigProperties; - getProperty(property: string) { - const value = this.properties["foundation"]; + getProperty(property: keyof CollieConfigProperties) { + const value = this.properties[property]; if (value) { this.logger.verbose( () => `loaded ${property}="${value}" from ${this.configFilePath}`, @@ -30,7 +31,7 @@ export class CollieConfig { } async setProperty( - property: "foundation", + property: keyof CollieConfigProperties, value: string, ) { this.properties[property] = value; diff --git a/src/model/CollieHub.ts b/src/model/CollieHub.ts index 2a754a2..57e52d3 100644 --- a/src/model/CollieHub.ts +++ b/src/model/CollieHub.ts @@ -1,16 +1,20 @@ import * as fs from "std/fs"; import { GitCliFacade } from "/api/git/GitCliFacade.ts"; import { CollieRepository } from "/model/CollieRepository.ts"; +import { CollieConfig } from "./CollieConfig.ts"; +import { Logger } from "../cli/Logger.ts"; export class CollieHub { constructor( private readonly git: GitCliFacade, private readonly repo: CollieRepository, + private readonly logger: Logger, + private readonly config: CollieConfig, ) {} private readonly hubCacheDirPath = [".collie", "hub"]; // hardcoding this is ok for now - readonly url = "https://github.com/meshcloud/collie-hub.git"; + readonly url = "https://github.com/meshcloud/collie-hub.git/"; public async importKitModule( id: string, @@ -40,7 +44,7 @@ export class CollieHub { await fs.copy(srcDir, frameworkDestDir, { overwrite: overwrite }); } - async updateHubClone() { + async cloneHub() { const hubCacheDir = this.repo.resolvePath(...this.hubCacheDirPath); // we do keep a git clone of the repo locally because copying on the local FS is much faster than downloading and @@ -52,12 +56,29 @@ export class CollieHub { ".git", ); const hasAlreadyCloned = await this.git.isRepo(hubCacheGitDir); + let collieHubVersion = this.config.getProperty("colliehubVersion"); - if (hasAlreadyCloned) { - await this.git.pull(hubCacheDir); - } else { + if (!hasAlreadyCloned) { await this.git.clone(hubCacheDir, this.url); } + if (!collieHubVersion) { + collieHubVersion = await this.git.getLatestTag(hubCacheDir); + await this.git.checkout(hubCacheDir, collieHubVersion); + this.config.setProperty("colliehubVersion", collieHubVersion!); + } + try { + const allTags = await this.git.getTags(hubCacheGitDir); + if (!allTags.includes(collieHubVersion)) { + throw new Error( + `version tag does not exist, possible are: ${allTags.split("\n")}`, + ); + } + } catch (error) { + this.logger.error(`${error}`); + Deno.exit(1); + } + //collie-hub version is set by the if block + await this.git.checkout(hubCacheDir, collieHubVersion!); return hubCacheDir; }