history: inspect command support

Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax
2025-04-10 21:35:18 +02:00
parent e12c042e86
commit e1c74199da
3 changed files with 165 additions and 6 deletions

View File

@@ -30,6 +30,48 @@ const tmpDir = fs.mkdtempSync(path.join(process.env.TEMP || os.tmpdir(), 'buildx
const maybe = !process.env.GITHUB_ACTIONS || (process.env.GITHUB_ACTIONS === 'true' && process.env.ImageOS && process.env.ImageOS.startsWith('ubuntu')) ? describe : describe.skip;
maybe('inspect', () => {
it('build', async () => {
const buildx = new Buildx();
const build = new Build({buildx: buildx});
fs.mkdirSync(tmpDir, {recursive: true});
await expect(
(async () => {
// prettier-ignore
const buildCmd = await buildx.getCommand([
'--builder', process.env.CTN_BUILDER_NAME ?? 'default',
'build', '-f', path.join(fixturesDir, 'hello.Dockerfile'),
'--metadata-file', build.getMetadataFilePath(),
fixturesDir
]);
await Exec.exec(buildCmd.command, buildCmd.args);
})()
).resolves.not.toThrow();
const metadata = build.resolveMetadata();
expect(metadata).toBeDefined();
const buildRef = build.resolveRef(metadata);
if (!buildRef) {
throw new Error('buildRef is undefined');
}
const [builderName, nodeName, ref] = buildRef.split('/');
expect(builderName).toBeDefined();
expect(nodeName).toBeDefined();
expect(ref).toBeDefined();
const history = new History({buildx: buildx});
const res = await history.inspect({
ref: ref,
builder: builderName
});
expect(res).toBeDefined();
expect(res?.Name).toBeDefined();
expect(res?.Ref).toBeDefined();
});
});
maybe('exportBuild', () => {
// prettier-ignore
test.each([

View File

@@ -28,7 +28,7 @@ import {Exec} from '../exec';
import {GitHub} from '../github';
import {Util} from '../util';
import {ExportRecordOpts, ExportRecordResponse, Summaries} from '../types/buildx/history';
import {ExportBuildOpts, ExportBuildResponse, InspectOpts, InspectResponse, Summaries} from '../types/buildx/history';
export interface HistoryOpts {
buildx?: Buildx;
@@ -44,7 +44,35 @@ export class History {
this.buildx = opts?.buildx || new Buildx();
}
public async export(opts: ExportRecordOpts): Promise<ExportRecordResponse> {
public async getCommand(args: Array<string>) {
return await this.buildx.getCommand(['history', ...args]);
}
public async getInspectCommand(args: Array<string>) {
return await this.getCommand(['inspect', ...args]);
}
public async inspect(opts: InspectOpts): Promise<InspectResponse> {
const args: Array<string> = ['--format', 'json'];
if (opts.builder) {
args.push('--builder', opts.builder);
}
if (opts.ref) {
args.push(opts.ref);
}
const cmd = await this.getInspectCommand(args);
return await Exec.getExecOutput(cmd.command, cmd.args, {
ignoreReturnCode: true,
silent: true
}).then(res => {
if (res.stderr.length > 0 && res.exitCode != 0) {
throw new Error(res.stderr.trim());
}
return <InspectResponse>JSON.parse(res.stdout);
});
}
public async export(opts: ExportBuildOpts): Promise<ExportBuildResponse> {
if (os.platform() === 'win32') {
throw new Error('Exporting a build record is currently not supported on Windows');
}

View File

@@ -14,12 +14,101 @@
* limitations under the License.
*/
export interface ExportRecordOpts {
export interface InspectOpts {
ref?: string;
builder?: string;
}
export type BuildStatus = 'completed' | 'running' | 'failed' | 'canceled';
export interface InspectResponse {
Name?: string;
Ref: string;
Context?: string;
Dockerfile?: string;
VCSRepository?: string;
VCSRevision?: string;
Target?: string;
Platform?: Array<string>;
KeepGitDir?: boolean;
NamedContexts?: Array<InspectKeyValueOutput>;
StartedAt?: Date;
CompletedAt?: Date;
Duration?: number;
Status?: BuildStatus;
Error?: InspectErrorOutput;
NumCompletedSteps: number;
NumTotalSteps: number;
NumCachedSteps: number;
BuildArgs?: Array<InspectKeyValueOutput>;
Labels?: Array<InspectKeyValueOutput>;
Config?: InspectConfigOutput;
Materials?: InspectMaterialOutput[];
Attachments?: InspectAttachmentOutput[];
Errors?: Array<string>;
}
export interface InspectConfigOutput {
Network?: string;
ExtraHosts?: Array<string>;
Hostname?: string;
CgroupParent?: string;
ImageResolveMode?: string;
MultiPlatform?: boolean;
NoCache?: boolean;
NoCacheFilter?: Array<string>;
ShmSize?: string;
Ulimit?: string;
CacheMountNS?: string;
DockerfileCheckConfig?: string;
SourceDateEpoch?: string;
SandboxHostname?: string;
RestRaw?: Array<InspectKeyValueOutput>;
}
export interface InspectMaterialOutput {
URI?: string;
Digests?: Array<string>;
}
export interface InspectAttachmentOutput {
Digest?: string;
Platform?: string;
Type?: string;
}
export interface InspectErrorOutput {
Code?: number;
Message?: string;
Name?: string;
Logs?: Array<string>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Sources?: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Stack?: any;
}
export interface InspectKeyValueOutput {
Name?: string;
Value?: string;
}
export interface ExportBuildOpts {
refs: Array<string>;
image?: string;
}
export interface ExportRecordResponse {
export interface ExportBuildResponse {
dockerbuildFilename: string;
dockerbuildSize: number;
summaries: Summaries;
@@ -29,10 +118,10 @@ export interface ExportRecordResponse {
}
export interface Summaries {
[ref: string]: RecordSummary;
[ref: string]: Summary;
}
export interface RecordSummary {
export interface Summary {
name: string;
status: string;
duration: string;