Skip to content

Commit 3c38811

Browse files
committed
sigstore: retry transient manifest lookups
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
1 parent ef8e8c8 commit 3c38811

4 files changed

Lines changed: 24 additions & 7 deletions

File tree

__tests__/buildx/imagetools.test.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,21 @@ beforeEach(() => {
4949
});
5050

5151
describe('inspectManifest', () => {
52-
it('retries transient manifest unknown errors when requested', async () => {
52+
// prettier-ignore
53+
it.each([
54+
[
55+
'Docker Hub missing tag',
56+
'ERROR: docker.io/library/alpine:codex-definitely-missing: not found'
57+
],
58+
[
59+
'GHCR missing digest',
60+
'ERROR: ghcr.io/docker/actions-toolkit-test@sha256:128e1cfe4e5f76af75df1121fccaf6da0cba412deec293ad988d7ade34499d09: not found'
61+
],
62+
[
63+
'AWS ECR manifest propagation',
64+
'ERROR: httpReadSeeker: failed open: content at https://public.ecr.aws/v2/q3b5f1u4/test-docker-action/manifests/sha256:76bc7984bdcf00ef5af953b7cb3de57ef39101cc091f4913c738b16cfbd26e53 not found: not found'
65+
]
66+
])('retries transient manifest unknown errors when requested (%s)', async (_name, stderr) => {
5367
vi.useFakeTimers();
5468

5569
const getCommand = vi.fn().mockResolvedValue({
@@ -62,7 +76,7 @@ describe('inspectManifest', () => {
6276
.mockResolvedValueOnce({
6377
exitCode: 1,
6478
stdout: '',
65-
stderr: 'ERROR: MANIFEST_UNKNOWN: manifest unknown'
79+
stderr: stderr
6680
})
6781
.mockResolvedValueOnce({
6882
exitCode: 0,

__tests__/sigstore/sigstore.test.itg.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,14 @@ for (const cosignVersion of signAttestationCosignVersions) {
106106

107107
const signResults = await sigstore.signAttestationManifests({
108108
imageNames: [imageName],
109-
imageDigest: buildDigest!
109+
imageDigest: buildDigest!,
110+
retryOnManifestUnknown: true
110111
});
111112
expect(Object.keys(signResults).length).toEqual(2);
112113

113114
const verifyResults = await sigstore.verifySignedManifests(signResults, {
114-
certificateIdentityRegexp: `^https://github.com/docker/actions-toolkit/.github/workflows/test.yml.*$`
115+
certificateIdentityRegexp: `^https://github.com/docker/actions-toolkit/.github/workflows/test.yml.*$`,
116+
retryOnManifestUnknown: true
115117
});
116118
expect(Object.keys(verifyResults).length).toEqual(2);
117119
}, 200000);

src/buildx/imagetools.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ export class ImageTools {
207207
if (!ImageTools.isManifestUnknownError(lastError.message) || attempt === retries - 1) {
208208
throw lastError;
209209
}
210-
core.info(`buildx imagetools inspect command failed with MANIFEST_UNKNOWN, retrying attempt ${attempt + 1}/${retries}...\n${lastError.message}`);
210+
core.info(`buildx imagetools inspect command failed with manifest not found, retrying attempt ${attempt + 1}/${retries}...\n${lastError.message}`);
211211
await new Promise(res => setTimeout(res, Math.pow(2, attempt) * 100));
212212
}
213213
}
@@ -228,6 +228,6 @@ export class ImageTools {
228228
}
229229

230230
private static isManifestUnknownError(message: string): boolean {
231-
return /(MANIFEST_UNKNOWN|manifest unknown|not found: not found)/i.test(message);
231+
return /(MANIFEST_UNKNOWN|manifest unknown)/i.test(message) || /:\s*not found$/i.test(message);
232232
}
233233
}

src/sigstore/sigstore.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,8 @@ export class Sigstore {
177177
const verifyResult = await this.verifyImageAttestation(attestationRef, {
178178
certificateIdentityRegexp: opts.certificateIdentityRegexp,
179179
noTransparencyLog: opts.noTransparencyLog || !signedRes.tlogID,
180-
retryOnManifestUnknown: opts.retryOnManifestUnknown
180+
retryOnManifestUnknown: opts.retryOnManifestUnknown,
181+
retryLimit: opts.retryLimit
181182
});
182183
core.info(`Signature manifest verified: https://oci.dag.dev/?image=${signedRes.imageName}@${verifyResult.signatureManifestDigest}`);
183184
result[attestationRef] = verifyResult;

0 commit comments

Comments
 (0)