Skip to content

Commit

Permalink
Merge branch 'main' into conroy/merge-back
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Dec 28, 2024
2 parents 99c9c6e + 7f6f94c commit 645f28e
Show file tree
Hide file tree
Showing 8 changed files with 515 additions and 17 deletions.
7 changes: 6 additions & 1 deletion packages/aws-cdk-lib/aws-ecr-assets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ asset hash.
Additionally, you can supply `buildSecrets`. Your system must have Buildkit
enabled, see https://docs.docker.com/build/buildkit/.

Also, similarly to `@aws-cdk/aws-s3-assets`, you can set the CDK_DOCKER environment
variable in order to provide a custom Docker executable command or path. This may sometimes
be needed when building in environments where the standard docker cannot be executed
(see https://github.com/aws/aws-cdk/issues/8460 for details).

SSH agent sockets or keys may be passed to docker build via `buildSsh`.

```ts
Expand Down Expand Up @@ -209,5 +214,5 @@ pull images from this repository.
If the pulling principal is not in the same account or is an AWS service that
doesn't assume a role in your account (e.g. AWS CodeBuild), you must either copy the image to a new repository, or
grant pull permissions on the resource policy of the repository. Since the repository is managed by the CDK bootstrap stack,
the following permissions must be granted there, or granted manually on the repository: "ecr:GetDownloadUrlForLayer",
the following permissions must be granted there, or granted manually on the repository: "ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage" and "ecr:BatchCheckLayerAvailability".
142 changes: 142 additions & 0 deletions packages/aws-cdk/lib/toolkit/cli-io-host.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import * as chalk from 'chalk';

/**
* Basic message structure for toolkit notifications.
* Messages are emitted by the toolkit and handled by the IoHost.
*/
interface IoMessage {
/**
* The time the message was emitted.
*/
readonly time: Date;

/**
* The log level of the message.
*/
readonly level: IoMessageLevel;

/**
* The action that triggered the message.
*/
readonly action: IoAction;

/**
* A short code uniquely identifying message type.
*/
readonly code: string;

/**
* The message text.
*/
readonly message: string;

/**
* If true, the message will be written to stdout
* regardless of any other parameters.
*
* @default false
*/
readonly forceStdout?: boolean;
}

export type IoMessageLevel = 'error' | 'warn' | 'info' | 'debug' | 'trace';

export type IoAction = 'synth' | 'list' | 'deploy' | 'destroy';

/**
* Options for the CLI IO host.
*/
interface CliIoHostOptions {
/**
* If true, the host will use TTY features like color.
*/
useTTY?: boolean;

/**
* Flag representing whether the current process is running in a CI environment.
* If true, the host will write all messages to stdout, unless log level is 'error'.
*
* @default false
*/
ci?: boolean;
}

/**
* A simple IO host for the CLI that writes messages to the console.
*/
export class CliIoHost {
private readonly pretty_messages: boolean;
private readonly ci: boolean;

constructor(options: CliIoHostOptions) {
this.pretty_messages = options.useTTY ?? process.stdout.isTTY ?? false;
this.ci = options.ci ?? false;
}

/**
* Notifies the host of a message.
* The caller waits until the notification completes.
*/
async notify(msg: IoMessage): Promise<void> {
const output = this.formatMessage(msg);

const stream = this.getStream(msg.level, msg.forceStdout ?? false);

return new Promise((resolve, reject) => {
stream.write(output, (err) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}

/**
* Determines which output stream to use based on log level and configuration.
*/
private getStream(level: IoMessageLevel, forceStdout: boolean) {
// For legacy purposes all log streams are written to stderr by default, unless
// specified otherwise, by passing `forceStdout`, which is used by the `data()` logging function, or
// if the CDK is running in a CI environment. This is because some CI environments will immediately
// fail if stderr is written to. In these cases, we detect if we are in a CI environment and
// write all messages to stdout instead.
if (forceStdout) {
return process.stdout;
}
if (level == 'error') return process.stderr;
return this.ci ? process.stdout : process.stderr;
}

/**
* Formats a message for console output with optional color support
*/
private formatMessage(msg: IoMessage): string {
// apply provided style or a default style if we're in TTY mode
let message_text = this.pretty_messages
? styleMap[msg.level](msg.message)
: msg.message;

// prepend timestamp if IoMessageLevel is DEBUG or TRACE. Postpend a newline.
return ((msg.level === 'debug' || msg.level === 'trace')
? `[${this.formatTime(msg.time)}] ${message_text}`
: message_text) + '\n';
}

/**
* Formats date to HH:MM:SS
*/
private formatTime(d: Date): string {
const pad = (n: number): string => n.toString().padStart(2, '0');
return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
}
}

export const styleMap: Record<IoMessageLevel, (str: string) => string> = {
error: chalk.red,
warn: chalk.yellow,
info: chalk.white,
debug: chalk.gray,
trace: chalk.gray,
};
Loading

0 comments on commit 645f28e

Please sign in to comment.