From e8b74e09d7e0a524be67df8b230f933723f76e30 Mon Sep 17 00:00:00 2001 From: Jan Michael Auer Date: Wed, 11 May 2022 11:09:24 +0200 Subject: [PATCH] fix(crates): Resume workspace publish (#392) The crates target is not able to resume a workspace publish because already published crates cannot be republished. This means a partially successful publish cannot be retried. To work around this, the crates target can skip publishing a crate if it already exists in this version. The downside of this is that we would silence errors when publishing the wrong version. --- src/targets/crates.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/targets/crates.ts b/src/targets/crates.ts index 857a59c8..a9a10f94 100644 --- a/src/targets/crates.ts +++ b/src/targets/crates.ts @@ -25,6 +25,13 @@ const CARGO_BIN = process.env.CARGO_BIN || DEFAULT_CARGO_BIN; */ const VERSION_ERROR = 'failed to select a version for the requirement'; +/** + * A message fragment emitted by cargo when publishing fails because the crate + * had already been published in this exact version. This happens especially + * when rerunning a workspace publish after it has failed in the middle. + */ +const REPUBLISH_ERROR = 'is already uploaded'; + /** * Maximum number of attempts including the initial one when publishing fails * due to a stale cache. After this number of retries, publishing fails. @@ -269,7 +276,17 @@ export class CratesTarget extends BaseTarget { let delay = RETRY_DELAY_SECS; this.logger.info(`Publishing ${crate.name}`); await withRetry( - () => spawnProcess(CARGO_BIN, args, { env }), + async () => { + try { + await spawnProcess(CARGO_BIN, args, { env }); + } catch (err) { + if (err instanceof Error && err.message.includes(REPUBLISH_ERROR)) { + this.logger.info(`Skipping ${crate.name}, version ${crate.version} already published`); + } else { + throw err; + } + } + }, MAX_ATTEMPTS, async err => {