@@ -16,25 +16,25 @@ export interface OCIFeatureRef {
16
16
registry : string ;
17
17
}
18
18
19
+ export interface OCILayer {
20
+ mediaType : string ;
21
+ digest : string ;
22
+ size : number ;
23
+ annotations : {
24
+ // 'org.opencontainers.image.ref.name': string;
25
+ 'org.opencontainers.image.title' : string ;
26
+ } ;
27
+ }
19
28
export interface OCIManifest {
29
+ digest ?: string ;
20
30
schemaVersion : number ;
21
31
mediaType : string ;
22
32
config : {
23
- mediaType : string ;
24
33
digest : string ;
34
+ mediaType : string ;
25
35
size : number ;
26
36
} ;
27
- layers : [
28
- {
29
- mediaType : string ;
30
- digest : string ;
31
- size : number ;
32
- annotations : {
33
- 'org.opencontainers.image.ref.name' : string ;
34
- 'org.opencontainers.image.title' : string ;
35
- } ;
36
- }
37
- ] ;
37
+ layers : OCILayer [ ] ;
38
38
}
39
39
40
40
export function getOCIFeatureSet ( output : Log , identifier : string , options : boolean | string | Record < string , boolean | string | undefined > , manifest : OCIManifest ) : FeatureSet {
@@ -223,13 +223,21 @@ export async function getGHCRtoken(output: Log, id: string) {
223
223
224
224
// -- Push
225
225
226
- export async function createManifest ( output : Log , pathToTgz : string ) : Promise < OCIManifest | undefined > {
226
+ export async function generateManifest ( output : Log , pathToTgz : string ) : Promise < OCIManifest | undefined > {
227
227
228
- /*const tgzLayer = */ calculateTgzLayer ( output , pathToTgz ) ;
229
- return undefined ;
228
+ const tgzLayer = await calculateTgzLayer ( output , pathToTgz ) ;
229
+ if ( ! tgzLayer ) {
230
+ output . write ( `Failed to calculate tgz layer.` , LogLevel . Error ) ;
231
+ return undefined ;
232
+ }
233
+
234
+ const { manifestObj, hash } = await calculateContentDigest ( output , tgzLayer ) ;
235
+ manifestObj . digest = `sha256:${ hash } ` ;
236
+
237
+ return manifestObj ;
230
238
}
231
239
232
- export async function calculateTgzLayer ( output : Log , pathToTgz : string ) : Promise < { digest : string ; size : number ; mediaType : string } | undefined > {
240
+ export async function calculateTgzLayer ( output : Log , pathToTgz : string ) : Promise < OCILayer | undefined > {
233
241
output . write ( `Creating manifest from ${ pathToTgz } ` , LogLevel . Trace ) ;
234
242
if ( ! ( await isLocalFile ( pathToTgz ) ) ) {
235
243
output . write ( `${ pathToTgz } does not exist.` , LogLevel . Error ) ;
@@ -238,13 +246,43 @@ export async function calculateTgzLayer(output: Log, pathToTgz: string): Promise
238
246
239
247
const tarBytes = fs . readFileSync ( pathToTgz ) ;
240
248
241
-
242
249
const tarSha256 = crypto . createHash ( 'sha256' ) . update ( tarBytes ) . digest ( 'hex' ) ;
243
250
output . write ( `${ pathToTgz } : sha256:${ tarSha256 } (size: ${ tarBytes . byteLength } )` , LogLevel . Trace ) ;
244
251
245
252
return {
253
+ mediaType : 'application/vnd.devcontainers.layer.v1+tar' ,
246
254
digest : `sha256:${ tarSha256 } ` ,
247
255
size : tarBytes . byteLength ,
248
- mediaType : 'application/octet-stream'
256
+ annotations : {
257
+ 'org.opencontainers.image.title' : path . basename ( pathToTgz ) ,
258
+ }
259
+ } ;
260
+ }
261
+
262
+ export async function calculateContentDigest ( output : Log , tgzLayer : OCILayer ) {
263
+ // {"schemaVersion":2,"mediaType":"application/vnd.oci.image.manifest.v1+json","config":{"mediaType":"application/vnd.devcontainers","digest":"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","size":0},"layers":[{"mediaType":"application/vnd.devcontainers.layer.v1+tar","digest":"sha256:b2006e7647191f7b47222ae48df049c6e21a4c5a04acfad0c4ef614d819de4c5","size":15872,"annotations":{"org.opencontainers.image.title":"go.tgz"}}] }
264
+
265
+ let manifest : OCIManifest = {
266
+ schemaVersion : 2 ,
267
+ mediaType : 'application/vnd.oci.image.manifest.v1+json' ,
268
+ config : {
269
+ mediaType : 'application/vnd.devcontainers' ,
270
+ digest : 'sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' ,
271
+ size : 0
272
+ } ,
273
+ layers : [
274
+ tgzLayer
275
+ ]
249
276
} ;
277
+
278
+ const manifestStringified = JSON . stringify ( manifest ) ;
279
+ const manifestHash = crypto . createHash ( 'sha256' ) . update ( manifestStringified ) . digest ( 'hex' ) ;
280
+ output . write ( `manifest: sha256:${ manifestHash } (size: ${ manifestHash . length } )` , LogLevel . Trace ) ;
281
+
282
+ return {
283
+ manifestStr : manifestStringified ,
284
+ manifestObj : manifest ,
285
+ hash : manifestHash ,
286
+ } ;
287
+
250
288
}
0 commit comments