fix(core): Stabilize CI/workflows and runtime: update CI images/metadata, improve streaming requests and image handling, and fix tests & package metadata

This commit is contained in:
2025-08-19 01:46:37 +00:00
parent 4b1c908b89
commit 414d7dd727
19 changed files with 444 additions and 243 deletions

View File

@@ -17,7 +17,10 @@ export class DockerImage {
return images;
}
public static async getImageByName(dockerHost: DockerHost, imageNameArg: string) {
public static async getImageByName(
dockerHost: DockerHost,
imageNameArg: string,
) {
const images = await this.getImages(dockerHost);
const result = images.find((image) => {
if (image.RepoTags) {
@@ -32,8 +35,8 @@ export class DockerImage {
public static async createFromRegistry(
dockerHostArg: DockerHost,
optionsArg: {
creationObject: interfaces.IImageCreationDescriptor
}
creationObject: interfaces.IImageCreationDescriptor;
},
): Promise<DockerImage> {
// lets create a sanatized imageUrlObject
const imageUrlObject: {
@@ -50,7 +53,7 @@ export class DockerImage {
const imageTag = imageUrlObject.imageUrl.split(':')[1];
if (imageUrlObject.imageTag) {
throw new Error(
`imageUrl ${imageUrlObject.imageUrl} can't be tagged with ${imageUrlObject.imageTag} because it is already tagged with ${imageTag}`
`imageUrl ${imageUrlObject.imageUrl} can't be tagged with ${imageUrlObject.imageTag} because it is already tagged with ${imageTag}`,
);
} else {
imageUrlObject.imageUrl = imageUrl;
@@ -65,12 +68,18 @@ export class DockerImage {
const response = await dockerHostArg.request(
'POST',
`/images/create?fromImage=${encodeURIComponent(
imageUrlObject.imageUrl
)}&tag=${encodeURIComponent(imageUrlObject.imageTag)}`
imageUrlObject.imageUrl,
)}&tag=${encodeURIComponent(imageUrlObject.imageTag)}`,
);
if (response.statusCode < 300) {
logger.log('info', `Successfully pulled image ${imageUrlObject.imageUrl} from the registry`);
const image = await DockerImage.getImageByName(dockerHostArg, imageUrlObject.imageOriginTag);
logger.log(
'info',
`Successfully pulled image ${imageUrlObject.imageUrl} from the registry`,
);
const image = await DockerImage.getImageByName(
dockerHostArg,
imageUrlObject.imageOriginTag,
);
return image;
} else {
logger.log('error', `Failed at the attempt of creating a new image`);
@@ -78,7 +87,7 @@ export class DockerImage {
}
/**
*
*
* @param dockerHostArg
* @param tarStreamArg
*/
@@ -87,13 +96,13 @@ export class DockerImage {
optionsArg: {
creationObject: interfaces.IImageCreationDescriptor;
tarStream: plugins.smartstream.stream.Readable;
}
},
): Promise<DockerImage> {
// Start the request for importing an image
const response = await dockerHostArg.requestStreaming(
'POST',
'/images/load',
optionsArg.tarStream
optionsArg.tarStream,
);
/**
@@ -144,7 +153,7 @@ export class DockerImage {
if (!loadedImageTag) {
throw new Error(
`Could not parse the loaded image info from Docker response.\nResponse was:\n${rawOutput}`
`Could not parse the loaded image info from Docker response.\nResponse was:\n${rawOutput}`,
);
}
@@ -153,34 +162,31 @@ export class DockerImage {
// "myrepo/myimage:latest" OR "sha256:someHash..."
// If Docker gave you an ID (e.g. "sha256:..."), you may need a separate
// DockerImage.getImageById method; or if you prefer, you can treat it as a name.
const newlyImportedImage = await DockerImage.getImageByName(dockerHostArg, loadedImageTag);
const newlyImportedImage = await DockerImage.getImageByName(
dockerHostArg,
loadedImageTag,
);
if (!newlyImportedImage) {
throw new Error(
`Image load succeeded, but no local reference found for "${loadedImageTag}".`
`Image load succeeded, but no local reference found for "${loadedImageTag}".`,
);
}
logger.log(
'info',
`Successfully imported image "${loadedImageTag}".`
);
logger.log('info', `Successfully imported image "${loadedImageTag}".`);
return newlyImportedImage;
}
public static async tagImageByIdOrName(
dockerHost: DockerHost,
idOrNameArg: string,
newTagArg: string
newTagArg: string,
) {
const response = await dockerHost.request(
'POST',
`/images/${encodeURIComponent(idOrNameArg)}/${encodeURIComponent(newTagArg)}`
`/images/${encodeURIComponent(idOrNameArg)}/${encodeURIComponent(newTagArg)}`,
);
}
public static async buildImage(dockerHostArg: DockerHost, dockerImageTag) {
@@ -249,23 +255,25 @@ export class DockerImage {
*/
public async exportToTarStream(): Promise<plugins.smartstream.stream.Readable> {
logger.log('info', `Exporting image ${this.RepoTags[0]} to tar stream.`);
const response = await this.dockerHost.requestStreaming('GET', `/images/${encodeURIComponent(this.RepoTags[0])}/get`);
const response = await this.dockerHost.requestStreaming(
'GET',
`/images/${encodeURIComponent(this.RepoTags[0])}/get`,
);
// Check if response is a Node.js stream
if (!response || typeof response.on !== 'function') {
throw new Error('Failed to get streaming response for image export');
}
let counter = 0;
const webduplexStream = new plugins.smartstream.SmartDuplex({
writeFunction: async (chunk, tools) => {
if (counter % 1000 === 0)
console.log(`Got chunk: ${counter}`);
if (counter % 1000 === 0) console.log(`Got chunk: ${counter}`);
counter++;
return chunk;
}
},
});
response.on('data', (chunk) => {
if (!webduplexStream.write(chunk)) {
response.pause();
@@ -274,16 +282,16 @@ export class DockerImage {
});
}
});
response.on('end', () => {
webduplexStream.end();
});
response.on('error', (error) => {
logger.log('error', `Error during image export: ${error.message}`);
webduplexStream.destroy(error);
});
return webduplexStream;
}
}