From 46fe0c6d63324b5f74ce0e65d6ab47051953cc48 Mon Sep 17 00:00:00 2001 From: Orfeas Kourkakis Date: Wed, 10 Jul 2024 13:13:49 +0300 Subject: [PATCH] fix(upload-charm): Use resource revision from upload-resource command (#147) Use resource revision number returned by upload-resource command when uploading a charm with resources. This replaces the previous behaviour when the action was listing resources and was using the latest available. Closes #139 Ref canonical/bundle-kubeflow#962 --- dist/channel/index.js | 29 +++++++++---- dist/check-libraries/index.js | 29 +++++++++---- dist/promote-charm/index.js | 29 +++++++++---- dist/release-charm/index.js | 29 +++++++++---- dist/release-libraries/index.js | 29 +++++++++---- dist/upload-bundle/index.js | 29 +++++++++---- dist/upload-charm/index.js | 29 +++++++++---- src/services/charmcraft/charmcraft.test.ts | 16 ++++---- src/services/charmcraft/charmcraft.ts | 48 ++++++++++++++++------ upload-charm/README.md | 5 ++- 10 files changed, 194 insertions(+), 78 deletions(-) diff --git a/dist/channel/index.js b/dist/channel/index.js index fbbd92a..c53bc4a 100644 --- a/dist/channel/index.js +++ b/dist/channel/index.js @@ -42758,13 +42758,24 @@ class Charmcraft { .filter(([name]) => !overrides || !Object.keys(overrides).includes(name)) .map(([name, image]) => __awaiter(this, void 0, void 0, function* () { if (this.uploadImage) { - yield this.uploadResource(image, charmName, name); + const { exitCode, stdout, stderr } = yield this.uploadResource(image, charmName, name); + if (exitCode !== 0) { + throw new Error(`Could not upload resource with error ${stderr}`); + } + const { revision } = JSON.parse(stdout); + const flag = `--resource=${name}:${revision}`; + const info = ` - ${name}: ${image}\n` + + ` resource-revision: ${revision}\n`; + flags.push(flag); + resourceInfo += info; + } + else { + const resourceFlag = yield this.buildResourceFlag(charmName, name, image); + if (!resourceFlag) + return; + flags.push(resourceFlag.flag); + resourceInfo += resourceFlag.info; } - const resourceFlag = yield this.buildResourceFlag(charmName, name, image); - if (!resourceFlag) - return; - flags.push(resourceFlag.flag); - resourceInfo += resourceFlag.info; }))); return { flags, resourceInfo }; }); @@ -42806,13 +42817,15 @@ class Charmcraft { const resourceDigest = yield (0, docker_1.getImageDigest)(resource_image); const args = [ 'upload-resource', - '--quiet', + '--format', + 'json', name, resource_name, '--image', resourceDigest, ]; - yield (0, exec_1.exec)('charmcraft', args, this.execOptions); + const execOutput = yield (0, exec_1.getExecOutput)('charmcraft', args, this.execOptions); + return execOutput; }); } buildResourceFlag(charmName, name, image) { diff --git a/dist/check-libraries/index.js b/dist/check-libraries/index.js index 8805468..7224aa8 100644 --- a/dist/check-libraries/index.js +++ b/dist/check-libraries/index.js @@ -42953,13 +42953,24 @@ class Charmcraft { .filter(([name]) => !overrides || !Object.keys(overrides).includes(name)) .map(([name, image]) => __awaiter(this, void 0, void 0, function* () { if (this.uploadImage) { - yield this.uploadResource(image, charmName, name); + const { exitCode, stdout, stderr } = yield this.uploadResource(image, charmName, name); + if (exitCode !== 0) { + throw new Error(`Could not upload resource with error ${stderr}`); + } + const { revision } = JSON.parse(stdout); + const flag = `--resource=${name}:${revision}`; + const info = ` - ${name}: ${image}\n` + + ` resource-revision: ${revision}\n`; + flags.push(flag); + resourceInfo += info; + } + else { + const resourceFlag = yield this.buildResourceFlag(charmName, name, image); + if (!resourceFlag) + return; + flags.push(resourceFlag.flag); + resourceInfo += resourceFlag.info; } - const resourceFlag = yield this.buildResourceFlag(charmName, name, image); - if (!resourceFlag) - return; - flags.push(resourceFlag.flag); - resourceInfo += resourceFlag.info; }))); return { flags, resourceInfo }; }); @@ -43001,13 +43012,15 @@ class Charmcraft { const resourceDigest = yield (0, docker_1.getImageDigest)(resource_image); const args = [ 'upload-resource', - '--quiet', + '--format', + 'json', name, resource_name, '--image', resourceDigest, ]; - yield (0, exec_1.exec)('charmcraft', args, this.execOptions); + const execOutput = yield (0, exec_1.getExecOutput)('charmcraft', args, this.execOptions); + return execOutput; }); } buildResourceFlag(charmName, name, image) { diff --git a/dist/promote-charm/index.js b/dist/promote-charm/index.js index ef51e2a..5d53442 100644 --- a/dist/promote-charm/index.js +++ b/dist/promote-charm/index.js @@ -42837,13 +42837,24 @@ class Charmcraft { .filter(([name]) => !overrides || !Object.keys(overrides).includes(name)) .map(([name, image]) => __awaiter(this, void 0, void 0, function* () { if (this.uploadImage) { - yield this.uploadResource(image, charmName, name); + const { exitCode, stdout, stderr } = yield this.uploadResource(image, charmName, name); + if (exitCode !== 0) { + throw new Error(`Could not upload resource with error ${stderr}`); + } + const { revision } = JSON.parse(stdout); + const flag = `--resource=${name}:${revision}`; + const info = ` - ${name}: ${image}\n` + + ` resource-revision: ${revision}\n`; + flags.push(flag); + resourceInfo += info; + } + else { + const resourceFlag = yield this.buildResourceFlag(charmName, name, image); + if (!resourceFlag) + return; + flags.push(resourceFlag.flag); + resourceInfo += resourceFlag.info; } - const resourceFlag = yield this.buildResourceFlag(charmName, name, image); - if (!resourceFlag) - return; - flags.push(resourceFlag.flag); - resourceInfo += resourceFlag.info; }))); return { flags, resourceInfo }; }); @@ -42885,13 +42896,15 @@ class Charmcraft { const resourceDigest = yield (0, docker_1.getImageDigest)(resource_image); const args = [ 'upload-resource', - '--quiet', + '--format', + 'json', name, resource_name, '--image', resourceDigest, ]; - yield (0, exec_1.exec)('charmcraft', args, this.execOptions); + const execOutput = yield (0, exec_1.getExecOutput)('charmcraft', args, this.execOptions); + return execOutput; }); } buildResourceFlag(charmName, name, image) { diff --git a/dist/release-charm/index.js b/dist/release-charm/index.js index a8dbdb1..862a960 100644 --- a/dist/release-charm/index.js +++ b/dist/release-charm/index.js @@ -42849,13 +42849,24 @@ class Charmcraft { .filter(([name]) => !overrides || !Object.keys(overrides).includes(name)) .map(([name, image]) => __awaiter(this, void 0, void 0, function* () { if (this.uploadImage) { - yield this.uploadResource(image, charmName, name); + const { exitCode, stdout, stderr } = yield this.uploadResource(image, charmName, name); + if (exitCode !== 0) { + throw new Error(`Could not upload resource with error ${stderr}`); + } + const { revision } = JSON.parse(stdout); + const flag = `--resource=${name}:${revision}`; + const info = ` - ${name}: ${image}\n` + + ` resource-revision: ${revision}\n`; + flags.push(flag); + resourceInfo += info; + } + else { + const resourceFlag = yield this.buildResourceFlag(charmName, name, image); + if (!resourceFlag) + return; + flags.push(resourceFlag.flag); + resourceInfo += resourceFlag.info; } - const resourceFlag = yield this.buildResourceFlag(charmName, name, image); - if (!resourceFlag) - return; - flags.push(resourceFlag.flag); - resourceInfo += resourceFlag.info; }))); return { flags, resourceInfo }; }); @@ -42897,13 +42908,15 @@ class Charmcraft { const resourceDigest = yield (0, docker_1.getImageDigest)(resource_image); const args = [ 'upload-resource', - '--quiet', + '--format', + 'json', name, resource_name, '--image', resourceDigest, ]; - yield (0, exec_1.exec)('charmcraft', args, this.execOptions); + const execOutput = yield (0, exec_1.getExecOutput)('charmcraft', args, this.execOptions); + return execOutput; }); } buildResourceFlag(charmName, name, image) { diff --git a/dist/release-libraries/index.js b/dist/release-libraries/index.js index 7237f84..0706e75 100644 --- a/dist/release-libraries/index.js +++ b/dist/release-libraries/index.js @@ -42980,13 +42980,24 @@ class Charmcraft { .filter(([name]) => !overrides || !Object.keys(overrides).includes(name)) .map(([name, image]) => __awaiter(this, void 0, void 0, function* () { if (this.uploadImage) { - yield this.uploadResource(image, charmName, name); + const { exitCode, stdout, stderr } = yield this.uploadResource(image, charmName, name); + if (exitCode !== 0) { + throw new Error(`Could not upload resource with error ${stderr}`); + } + const { revision } = JSON.parse(stdout); + const flag = `--resource=${name}:${revision}`; + const info = ` - ${name}: ${image}\n` + + ` resource-revision: ${revision}\n`; + flags.push(flag); + resourceInfo += info; + } + else { + const resourceFlag = yield this.buildResourceFlag(charmName, name, image); + if (!resourceFlag) + return; + flags.push(resourceFlag.flag); + resourceInfo += resourceFlag.info; } - const resourceFlag = yield this.buildResourceFlag(charmName, name, image); - if (!resourceFlag) - return; - flags.push(resourceFlag.flag); - resourceInfo += resourceFlag.info; }))); return { flags, resourceInfo }; }); @@ -43028,13 +43039,15 @@ class Charmcraft { const resourceDigest = yield (0, docker_1.getImageDigest)(resource_image); const args = [ 'upload-resource', - '--quiet', + '--format', + 'json', name, resource_name, '--image', resourceDigest, ]; - yield (0, exec_1.exec)('charmcraft', args, this.execOptions); + const execOutput = yield (0, exec_1.getExecOutput)('charmcraft', args, this.execOptions); + return execOutput; }); } buildResourceFlag(charmName, name, image) { diff --git a/dist/upload-bundle/index.js b/dist/upload-bundle/index.js index 002be14..ffaa138 100644 --- a/dist/upload-bundle/index.js +++ b/dist/upload-bundle/index.js @@ -42828,13 +42828,24 @@ class Charmcraft { .filter(([name]) => !overrides || !Object.keys(overrides).includes(name)) .map(([name, image]) => __awaiter(this, void 0, void 0, function* () { if (this.uploadImage) { - yield this.uploadResource(image, charmName, name); + const { exitCode, stdout, stderr } = yield this.uploadResource(image, charmName, name); + if (exitCode !== 0) { + throw new Error(`Could not upload resource with error ${stderr}`); + } + const { revision } = JSON.parse(stdout); + const flag = `--resource=${name}:${revision}`; + const info = ` - ${name}: ${image}\n` + + ` resource-revision: ${revision}\n`; + flags.push(flag); + resourceInfo += info; + } + else { + const resourceFlag = yield this.buildResourceFlag(charmName, name, image); + if (!resourceFlag) + return; + flags.push(resourceFlag.flag); + resourceInfo += resourceFlag.info; } - const resourceFlag = yield this.buildResourceFlag(charmName, name, image); - if (!resourceFlag) - return; - flags.push(resourceFlag.flag); - resourceInfo += resourceFlag.info; }))); return { flags, resourceInfo }; }); @@ -42876,13 +42887,15 @@ class Charmcraft { const resourceDigest = yield (0, docker_1.getImageDigest)(resource_image); const args = [ 'upload-resource', - '--quiet', + '--format', + 'json', name, resource_name, '--image', resourceDigest, ]; - yield (0, exec_1.exec)('charmcraft', args, this.execOptions); + const execOutput = yield (0, exec_1.getExecOutput)('charmcraft', args, this.execOptions); + return execOutput; }); } buildResourceFlag(charmName, name, image) { diff --git a/dist/upload-charm/index.js b/dist/upload-charm/index.js index 54d792d..5d46b19 100644 --- a/dist/upload-charm/index.js +++ b/dist/upload-charm/index.js @@ -42868,13 +42868,24 @@ class Charmcraft { .filter(([name]) => !overrides || !Object.keys(overrides).includes(name)) .map(([name, image]) => __awaiter(this, void 0, void 0, function* () { if (this.uploadImage) { - yield this.uploadResource(image, charmName, name); + const { exitCode, stdout, stderr } = yield this.uploadResource(image, charmName, name); + if (exitCode !== 0) { + throw new Error(`Could not upload resource with error ${stderr}`); + } + const { revision } = JSON.parse(stdout); + const flag = `--resource=${name}:${revision}`; + const info = ` - ${name}: ${image}\n` + + ` resource-revision: ${revision}\n`; + flags.push(flag); + resourceInfo += info; + } + else { + const resourceFlag = yield this.buildResourceFlag(charmName, name, image); + if (!resourceFlag) + return; + flags.push(resourceFlag.flag); + resourceInfo += resourceFlag.info; } - const resourceFlag = yield this.buildResourceFlag(charmName, name, image); - if (!resourceFlag) - return; - flags.push(resourceFlag.flag); - resourceInfo += resourceFlag.info; }))); return { flags, resourceInfo }; }); @@ -42916,13 +42927,15 @@ class Charmcraft { const resourceDigest = yield (0, docker_1.getImageDigest)(resource_image); const args = [ 'upload-resource', - '--quiet', + '--format', + 'json', name, resource_name, '--image', resourceDigest, ]; - yield (0, exec_1.exec)('charmcraft', args, this.execOptions); + const execOutput = yield (0, exec_1.getExecOutput)('charmcraft', args, this.execOptions); + return execOutput; }); } buildResourceFlag(charmName, name, image) { diff --git a/src/services/charmcraft/charmcraft.test.ts b/src/services/charmcraft/charmcraft.test.ts index b6ade96..184adaf 100644 --- a/src/services/charmcraft/charmcraft.test.ts +++ b/src/services/charmcraft/charmcraft.test.ts @@ -135,13 +135,15 @@ describe('the charmcraft service', () => { const digest = `somedigest`; const charmcraft = new Charmcraft('token', true); - const mockedExec = jest.spyOn(exec, 'exec').mockResolvedValue(0); - - jest.spyOn(exec, 'getExecOutput').mockResolvedValue({ - exitCode: 0, - stderr: '', - stdout: digest, - }); + jest.spyOn(exec, 'exec').mockResolvedValue(0); + + const mockedExec = jest + .spyOn(exec, 'getExecOutput') + .mockResolvedValue({ + exitCode: 0, + stderr: '', + stdout: digest, + }); await charmcraft.uploadResource( 'placeholder-image', diff --git a/src/services/charmcraft/charmcraft.ts b/src/services/charmcraft/charmcraft.ts index e84ef48..27b15b2 100644 --- a/src/services/charmcraft/charmcraft.ts +++ b/src/services/charmcraft/charmcraft.ts @@ -51,18 +51,33 @@ class Charmcraft { ) .map(async ([name, image]) => { if (this.uploadImage) { - await this.uploadResource(image, charmName, name); + const { exitCode, stdout, stderr } = await this.uploadResource( + image, + charmName, + name, + ); + if (exitCode !== 0) { + throw new Error(`Could not upload resource with error ${stderr}`); + } + const { revision } = JSON.parse(stdout); + const flag = `--resource=${name}:${revision}`; + const info = + ` - ${name}: ${image}\n` + + ` resource-revision: ${revision}\n`; + flags.push(flag); + resourceInfo += info; + } else { + const resourceFlag = await this.buildResourceFlag( + charmName, + name, + image, + ); + + if (!resourceFlag) return; + + flags.push(resourceFlag.flag); + resourceInfo += resourceFlag.info; } - const resourceFlag = await this.buildResourceFlag( - charmName, - name, - image, - ); - - if (!resourceFlag) return; - - flags.push(resourceFlag.flag); - resourceInfo += resourceFlag.info; }), ); return { flags, resourceInfo }; @@ -126,13 +141,20 @@ class Charmcraft { const args = [ 'upload-resource', - '--quiet', + '--format', + 'json', name, resource_name, '--image', resourceDigest, ]; - await exec('charmcraft', args, this.execOptions); + + const execOutput = await getExecOutput( + 'charmcraft', + args, + this.execOptions, + ); + return execOutput; } async buildResourceFlag(charmName: string, name: string, image: string) { diff --git a/upload-charm/README.md b/upload-charm/README.md index 0929bc4..f8612fd 100644 --- a/upload-charm/README.md +++ b/upload-charm/README.md @@ -17,8 +17,9 @@ This action is used to upload a charm to charmhub.io. ### OCI Image -When uploading a charm with OCI image resources, a new revision of the OCI image will be published -and attached to the release. It is possible to disable this behavior using either `upload-image: false` +When uploading a charm with OCI image resources, the action will try to upload the OCI image to Charmhub +and attach it to the release. If the image already exists in Charmhub, then it will use an existing revision +corresponding to that image. It is possible to disable this behavior using either `upload-image: false` or by providing `resource-overrides` pointing at a specific existing revision. ### Files