add tests for index upload
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
uploadOCIImageManifest
|
uploadOCIImageManifest,
|
||||||
|
uploadOCIIndexManifest
|
||||||
// uploadOCIIndexManifest
|
// uploadOCIIndexManifest
|
||||||
} from '../src/ghcr-client'
|
} from '../src/ghcr-client'
|
||||||
import * as ociContainer from '../src/oci-container'
|
import * as ociContainer from '../src/oci-container'
|
||||||
@@ -178,6 +179,63 @@ function configureFetchMock(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
describe('uploadOCIIndexManifest', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
fetchMock = jest.spyOn(global, 'fetch').mockImplementation()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('uploads the tagged manifest with the appropriate tag', async () => {
|
||||||
|
const { manifest, sha } = testIndexManifest()
|
||||||
|
const tag = 'sha-1234'
|
||||||
|
|
||||||
|
configureFetchMock(fetchMock, {
|
||||||
|
putManifestMock: putManifestSuccessful(sha, tag)
|
||||||
|
})
|
||||||
|
|
||||||
|
await uploadOCIIndexManifest(token, registry, repository, manifest, tag)
|
||||||
|
|
||||||
|
expect(fetchMock).toHaveBeenCalledTimes(1)
|
||||||
|
expect(
|
||||||
|
fetchMock.mock.calls.filter(call => call[1].method === 'PUT')
|
||||||
|
).toHaveLength(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws an error if a manifest upload fails', async () => {
|
||||||
|
const { manifest, blobs } = testImageManifest()
|
||||||
|
|
||||||
|
configureFetchMock(fetchMock, {
|
||||||
|
checkBlobMock: checkBlobAllExistingBlobs,
|
||||||
|
initiateBlobUploadMock: initiateBlobUploadSuccessForAllBlobs,
|
||||||
|
putBlobMock: putBlobSuccess,
|
||||||
|
putManifestMock: putManifestFailure
|
||||||
|
})
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
uploadOCIImageManifest(token, registry, repository, manifest, blobs)
|
||||||
|
).rejects.toThrow(
|
||||||
|
'Unexpected 400 Bad Request response from manifest upload. Errors: BAD_REQUEST - tag already exists.'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws an error if the returned digest does not match the precalculated one', async () => {
|
||||||
|
const { manifest, sha, blobs } = testImageManifest()
|
||||||
|
|
||||||
|
configureFetchMock(fetchMock, {
|
||||||
|
checkBlobMock: checkBlobAllExistingBlobs,
|
||||||
|
initiateBlobUploadMock: initiateBlobUploadSuccessForAllBlobs,
|
||||||
|
putBlobMock: putBlobSuccess,
|
||||||
|
putManifestMock: putManifestSuccessful('some-garbage-digest', sha)
|
||||||
|
})
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
uploadOCIImageManifest(token, registry, repository, manifest, blobs)
|
||||||
|
).rejects.toThrow(
|
||||||
|
`Digest mismatch. Expected ${sha}, got some-garbage-digest.`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('uploadOCIImageManifest', () => {
|
describe('uploadOCIImageManifest', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
@@ -196,7 +254,6 @@ describe('uploadOCIImageManifest', () => {
|
|||||||
|
|
||||||
await uploadOCIImageManifest(token, registry, repository, manifest, blobs)
|
await uploadOCIImageManifest(token, registry, repository, manifest, blobs)
|
||||||
|
|
||||||
// TODO: See what calls there are
|
|
||||||
expect(fetchMock).toHaveBeenCalledTimes(10)
|
expect(fetchMock).toHaveBeenCalledTimes(10)
|
||||||
expect(
|
expect(
|
||||||
fetchMock.mock.calls.filter(call => call[1].method === 'HEAD')
|
fetchMock.mock.calls.filter(call => call[1].method === 'HEAD')
|
||||||
@@ -228,7 +285,6 @@ describe('uploadOCIImageManifest', () => {
|
|||||||
semver
|
semver
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: See what calls there are
|
|
||||||
expect(fetchMock).toHaveBeenCalledTimes(10)
|
expect(fetchMock).toHaveBeenCalledTimes(10)
|
||||||
expect(
|
expect(
|
||||||
fetchMock.mock.calls.filter(call => call[1].method === 'HEAD')
|
fetchMock.mock.calls.filter(call => call[1].method === 'HEAD')
|
||||||
@@ -388,19 +444,6 @@ describe('uploadOCIImageManifest', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('uploadOCIIndexManifest', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
jest.clearAllMocks()
|
|
||||||
fetchMock = jest.spyOn(global, 'fetch').mockImplementation()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('uploads the tagged manifest with the appropriate tag', async () => {})
|
|
||||||
|
|
||||||
it('throws an error if a manifest upload fails', async () => {})
|
|
||||||
|
|
||||||
it('throws an error if the returned digest does not match the precalculated one', async () => {})
|
|
||||||
})
|
|
||||||
|
|
||||||
function testImageManifest(): {
|
function testImageManifest(): {
|
||||||
manifest: ociContainer.OCIImageManifest
|
manifest: ociContainer.OCIImageManifest
|
||||||
sha: string
|
sha: string
|
||||||
@@ -452,6 +495,20 @@ function testImageManifest(): {
|
|||||||
return { manifest, sha, blobs }
|
return { manifest, sha, blobs }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testIndexManifest(): {
|
||||||
|
manifest: ociContainer.OCIIndexManifest
|
||||||
|
sha: string
|
||||||
|
} {
|
||||||
|
const manifest = ociContainer.createReferrerTagManifest(
|
||||||
|
'attestation-digest',
|
||||||
|
1234,
|
||||||
|
new Date(),
|
||||||
|
new Date()
|
||||||
|
)
|
||||||
|
const sha = ociContainer.sha256Digest(manifest)
|
||||||
|
return { manifest, sha }
|
||||||
|
}
|
||||||
|
|
||||||
// We expect all fetch calls to have auth headers set
|
// We expect all fetch calls to have auth headers set
|
||||||
// This function verifies that given an request config.
|
// This function verifies that given an request config.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="116" height="20" role="img" aria-label="Coverage: 95.01%"><title>Coverage: 95.01%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="116" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="63" height="20" fill="#555"/><rect x="63" width="53" height="20" fill="#4c1"/><rect width="116" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">Coverage</text><text x="325" y="140" transform="scale(.1)" fill="#fff" textLength="530">Coverage</text><text aria-hidden="true" x="885" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">95.01%</text><text x="885" y="140" transform="scale(.1)" fill="#fff" textLength="430">95.01%</text></g></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="116" height="20" role="img" aria-label="Coverage: 96.77%"><title>Coverage: 96.77%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="116" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="63" height="20" fill="#555"/><rect x="63" width="53" height="20" fill="#4c1"/><rect width="116" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">Coverage</text><text x="325" y="140" transform="scale(.1)" fill="#fff" textLength="530">Coverage</text><text aria-hidden="true" x="885" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">96.77%</text><text x="885" y="140" transform="scale(.1)" fill="#fff" textLength="430">96.77%</text></g></svg>
|
||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Reference in New Issue
Block a user