Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: make sure noColor option is honored #3138

Merged
merged 21 commits into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions packages/@cdktf/cli-core/src/lib/cdktf-project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ export class CdktfProject {
);
}

public async synth() {
public async synth(noColor?: boolean) {
this.onUpdate({
type: "synthesizing",
});
Expand All @@ -358,6 +358,7 @@ export class CdktfProject {
this.outDir,
this.workingDirectory,
false,
noColor,
this.synthOrigin
);

Expand Down Expand Up @@ -386,7 +387,7 @@ export class CdktfProject {
public async diff(opts: DiffOptions = {}) {
const stacks = opts.skipSynth
? await this.readSynthesizedStacks()
: await this.synth();
: await this.synth(opts.noColor);
const stack = this.getStackExecutor(
getSingleStack(stacks, opts?.stackName, "diff")
);
Expand Down Expand Up @@ -484,7 +485,7 @@ export class CdktfProject {
public async deploy(opts: MutationOptions = {}) {
const stacks = opts.skipSynth
? await this.readSynthesizedStacks()
: await this.synth();
: await this.synth(opts.noColor);
const stacksToRun = getMultipleStacks(stacks, opts.stackNames, "deploy");
if (!opts.ignoreMissingStackDependencies) {
checkIfAllDependenciesAreIncluded(stacksToRun);
Expand Down Expand Up @@ -542,7 +543,7 @@ export class CdktfProject {
public async destroy(opts: MutationOptions = {}) {
const stacks = opts.skipSynth
? await this.readSynthesizedStacks()
: await this.synth();
: await this.synth(opts.noColor);
const stacksToRun = getMultipleStacks(stacks, opts.stackNames, "destroy");

if (!opts.ignoreMissingStackDependencies) {
Expand Down
4 changes: 4 additions & 0 deletions packages/@cdktf/cli-core/src/lib/models/terraform-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ export class TerraformCli implements Terraform {
cwd: this.workdir,
env: process.env,
signal: this.abortSignal,
noColor: opts.noColor,
},
this.onStdout("init"),
this.onStderr("init")
Expand Down Expand Up @@ -249,6 +250,7 @@ export class TerraformCli implements Terraform {
cwd: this.workdir,
env: process.env,
signal: this.abortSignal,
noColor,
},
this.onStdout("plan", [VariableRequiredFilter]),
this.onStderr("plan", [VariableRequiredFilter])
Expand Down Expand Up @@ -411,6 +413,7 @@ export class TerraformCli implements Terraform {
cwd: this.workdir,
env: process.env,
signal: this.abortSignal,
noColor: true,
},
this.onStdout("version"),
this.onStderr("version")
Expand All @@ -430,6 +433,7 @@ export class TerraformCli implements Terraform {
cwd: this.workdir,
env: process.env,
signal: this.abortSignal,
noColor: true,
},
// We don't need to log the output here since we use it later on
() => {}, // eslint-disable-line @typescript-eslint/no-empty-function
Expand Down
2 changes: 2 additions & 0 deletions packages/@cdktf/cli-core/src/lib/synth-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export class SynthStack {
outdir: string,
workingDirectory = process.cwd(),
graceful = false, // will not exit the process but rethrow the error instead
noColor = false,
synthOrigin?: SynthOrigin
): Promise<SynthesizedStack[]> {
// start performance timer
Expand Down Expand Up @@ -120,6 +121,7 @@ might fail while synthesizing with an out of memory error.`);
},
cwd: workingDirectory,
signal: abortSignal,
noColor: noColor,
});
} catch (e: any) {
const errorOutput = chalkColour`{redBright cdktf encountered an error while synthesizing}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,20 @@ import { CdktfProject, init, get } from "../../lib/index";
import { spawn } from "@cdktf/node-pty-prebuilt-multiarch";
import { exec, Language } from "@cdktf/commons";

// this is required for the get() call in beforeAll() to work
let execMockActive = false;

jest.mock("@cdktf/commons", () => {
const originalModule = jest.requireActual("@cdktf/commons");

return {
__esmodule: true,
...originalModule,
// exec: jest.fn().mockImplementation(originalModule.exec),
exec: jest.fn().mockImplementation(async (_binary, _args) => {
exec: jest.fn().mockImplementation(async (...args: any[]) => {
// Fake all commands that we invoke
return Promise.resolve(JSON.stringify({}));

if (execMockActive) return Promise.resolve(JSON.stringify({}));
return originalModule.exec(...args);
}),
};
});
Expand Down Expand Up @@ -127,6 +131,8 @@ describe("terraform parallelism", () => {
process.env.CDKTF_EXPERIMENTAL_PROVIDER_SCHEMA_CACHE_PATH,
});

execMockActive = true;

inNewWorkingDirectory = function inNewWorkingDirectory() {
const wd = fs.mkdtempSync(path.join(os.tmpdir(), "cdktf."));
const outDir = path.resolve(wd, "out");
Expand Down
2 changes: 1 addition & 1 deletion packages/@cdktf/commons/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"fs-extra": "^11.1.1",
"is-valid-domain": "^0.1.6",
"log4js": "^6.9.1",
"uuid": "^9.0.0"
"uuid": "^9.0.1"
},
"devDependencies": {
"@types/follow-redirects": "^1.14.1",
Expand Down
8 changes: 8 additions & 0 deletions packages/@cdktf/commons/src/logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { configure, getLogger } from "log4js";
import * as fs from "fs-extra";
import * as path from "path";
import * as Sentry from "@sentry/node";
import { hasNoColorFlagOrEnv } from "./util";

const cliLogger = getLogger();
const logger = {
Expand Down Expand Up @@ -81,6 +82,13 @@ if (
},
categories: { default: { appenders: ["cdktf"], level: "debug" } },
});
} else {
const layoutType = hasNoColorFlagOrEnv() ? "basic" : "colored";

configure({
appenders: { out: { type: "stdout", layout: { type: layoutType } } },
categories: { default: { appenders: ["out"], level: "info" } },
});
}

const processLoggerDebug = (chunk: Buffer | string | Uint8Array) => {
Expand Down
96 changes: 75 additions & 21 deletions packages/@cdktf/commons/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import * as path from "path";
import { processLoggerError, processLoggerDebug } from "./logging";
import { IManifest, Manifest } from "cdktf";
import * as config from "./config";
import stripAnsi from "strip-ansi";

export async function shell(
program: string,
args: string[] = [],
options: SpawnOptions = {}
options: SpawnOptions & { noColor?: boolean } = {}
) {
const stderr = new Array<string | Uint8Array>();
const stdout = new Array<string>();
Expand All @@ -22,18 +23,32 @@ export async function shell(
program,
args,
options,
(chunk: Buffer) => {
stdout.push(chunk.toString());
console.log(chunk.toString());
(chunk: string) => {
const sanitizedChunk = options.noColor
? stripAnsi(chunk.toLocaleString())
: chunk.toLocaleString();
stdout.push(sanitizedChunk);
console.log(sanitizedChunk);
},
(chunk: string | Uint8Array) => stderr.push(chunk)
(chunk: string | Uint8Array) => {
const sanitizedChunk = options.noColor
? stripAnsi(chunk.toLocaleString())
: chunk.toLocaleString();
stderr.push(sanitizedChunk);
}
);
} catch (e: any) {
if (stderr.length > 0) {
e.stderr = stderr.map((chunk) => chunk.toString()).join("");
if (options.noColor) {
e.stderr = stripAnsi(e.stderr);
}
}
if (stdout.length > 0) {
e.stdout = stdout.join("");
if (options.noColor) {
e.stdout = stripAnsi(e.stdout);
}
}
throw e;
}
Expand Down Expand Up @@ -68,42 +83,60 @@ export async function mkdtemp(closure: (dir: string) => Promise<void>) {
export const exec = async (
command: string,
args: string[],
options: SpawnOptions,
stdout?: (chunk: Buffer) => any,
options: SpawnOptions & { noColor?: boolean },
stdout?: (chunk: string) => any,
stderr?: (chunk: string | Uint8Array) => any,
sendToStderr = true
): Promise<string> => {
// if options.noColor is not set, checking the flags & environment if it should be set
// This is required for collectDebugInformation() which does not have knowledge about flags
if (typeof options.noColor !== "boolean" && hasNoColorFlagOrEnv()) {
options.noColor = true;
}

return new Promise((ok, ko) => {
const child = spawn(command, args, options);
const out = new Array<Buffer>();
const err = new Array<string | Uint8Array>();
const out = new Array<string>();
const err = new Array<string>();
if (stdout !== undefined) {
child.stdout?.on("data", (chunk: Buffer) => {
processLoggerDebug(chunk);
out.push(chunk);
stdout(chunk);
const sanitizedChunk = options.noColor
? stripAnsi(chunk.toLocaleString())
: chunk.toLocaleString();
processLoggerDebug(sanitizedChunk);
out.push(sanitizedChunk);
stdout(sanitizedChunk);
});
} else {
child.stdout?.on("data", (chunk: Buffer) => {
processLoggerDebug(chunk);
out.push(chunk);
const sanitizedChunk = options.noColor
? stripAnsi(chunk.toLocaleString())
: chunk.toLocaleString();
processLoggerDebug(sanitizedChunk);
out.push(sanitizedChunk);
});
}
if (stderr !== undefined) {
child.stderr?.on("data", (chunk: string | Uint8Array) => {
processLoggerError(chunk);
const sanitizedChunk = options.noColor
? stripAnsi(chunk.toLocaleString())
: chunk.toLocaleString();
processLoggerError(sanitizedChunk);
if (sendToStderr) {
stderr(chunk);
stderr(sanitizedChunk);
}
err.push(chunk);
err.push(sanitizedChunk);
});
} else {
child.stderr?.on("data", (chunk: string | Uint8Array) => {
processLoggerError(chunk);
const sanitizedChunk = options.noColor
? stripAnsi(chunk.toLocaleString())
: chunk.toLocaleString();
processLoggerError(sanitizedChunk);
if (sendToStderr) {
process.stderr.write(chunk);
process.stderr.write(sanitizedChunk);
}
err.push(chunk);
err.push(sanitizedChunk);
});
}
child.once("error", (err: any) => ko(err));
Expand All @@ -113,7 +146,7 @@ export const exec = async (
(error as any).stderr = err.map((chunk) => chunk.toString()).join("");
return ko(error);
}
return ok(Buffer.concat(out).toString("utf-8"));
return ok(out.join(""));
});
});
};
Expand Down Expand Up @@ -211,3 +244,24 @@ export async function ensureAllSettledBeforeThrowing(
throw e;
}
}

/**
* returns true if --no-color is passed as CLI flag or the env var FORCE_COLOR is set to "0"
* Used for cases where we can't pass down the noColor flag (e.g. when collecting debug information from the environment)
* This is the same behavior as the `chalk` lib we use for coloring output
*/
export function hasNoColorFlagOrEnv(): boolean {
return hasFlag("no-color") || process.env.FORCE_COLOR === "0";
}

// From: https://github.com/sindresorhus/has-flag/blob/main/index.js
// as used in https://github.com/chalk/chalk
function hasFlag(flag: string) {
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
const position = process.argv.indexOf(prefix + flag);
const terminatorPosition = process.argv.indexOf("--");
return (
position !== -1 &&
(terminatorPosition === -1 || position < terminatorPosition)
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import * as fs from "fs-extra";
import * as path from "path";
import { generateProviderBindingsFromSchema } from "..";
import { mkdtemp } from "../util";
import { mkdtemp } from "@cdktf/commons";
import { edgeSchema } from "./edge-provider-schema";

describe("Edge Provider Schema", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import * as path from "path";
import * as fs from "fs-extra";
import { glob } from "glob";
import { mkdtemp } from "../util";
import { mkdtemp } from "@cdktf/commons";
import { ConstructsMaker } from "../get/constructs-maker";
import { Language, TerraformProviderConstraint } from "@cdktf/commons";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
// Copyright (c) HashiCorp, Inc
// SPDX-License-Identifier: MPL-2.0
import * as fs from "fs";
import { withTempDir } from "../../util";
import { Language, TerraformModuleConstraint } from "@cdktf/commons";
import {
Language,
TerraformModuleConstraint,
withTempDir,
} from "@cdktf/commons";
import { ConstructsMaker } from "../constructs-maker";
import * as path from "path";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import * as fs from "fs-extra";
import * as path from "path";
import { CodeMaker } from "codemaker";
import { mkdtemp } from "../util";
import { mkdtemp } from "@cdktf/commons";
import * as srcmak from "jsii-srcmak";
import {
TerraformDependencyConstraint,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ export class TerraformProviderGenerator {
)}`
);
throw new Error(
`Could not find provider with constraint ${providerConstraint}`
`Could not find provider with constraint ${JSON.stringify(
providerConstraint
)}`
);
}

Expand Down
Loading
Loading