Skip to content

Commit 51cdf87

Browse files
committed
Use manifest.json to generate hash
1 parent 494c470 commit 51cdf87

File tree

2 files changed

+57
-40
lines changed

2 files changed

+57
-40
lines changed

src/LayerCache.ts

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,22 @@ import * as core from '@actions/core'
55
import * as cache from '@actions/cache'
66
import { ExecOptions } from '@actions/exec/lib/interfaces'
77
import { promises as fs } from 'fs'
8-
import { assertManifests, Manifest, Manifests } from './Tar'
8+
import { assertManifests, Manifest, Manifests, loadManifests, loadRawManifests } from './Tar'
99
import format from 'string-format'
1010
import PromisePool from 'native-promise-pool'
1111

1212
class LayerCache {
13-
// repotag: string
14-
ids: string[]
15-
unformattedOrigianlKey: string = ''
16-
restoredOriginalKey?: string
17-
// tarFile: string = ''
13+
ids: string[] = []
14+
unformattedSaveKey: string = ''
15+
restoredRootKey: string = ''
1816
imagesDir: string = path.resolve(`${process.cwd()}/./.action-docker-layer-caching-docker_images`)
1917
enabledParallel = true
20-
// unpackedTarDir: string = ''
21-
// manifests: Manifests = []
2218
concurrency: number = 4
2319

2420
static ERROR_CACHE_ALREAD_EXISTS_STR = `Cache already exists`
2521
static ERROR_LAYER_CACHE_NOT_FOUND_STR = `Layer cache not found`
2622

2723
constructor(ids: string[]) {
28-
// this.repotag = repotag
2924
this.ids = ids
3025
}
3126

@@ -39,10 +34,8 @@ class LayerCache {
3934
}
4035

4136
async store(key: string) {
42-
this.unformattedOrigianlKey = key
43-
// this.originalKeyToStore = format(key, {
44-
// hash: this.getIdhashesPathFriendly()
45-
// })
37+
this.unformattedSaveKey = key
38+
4639
await this.saveImageAsUnpacked()
4740
if (this.enabledParallel) {
4841
await this.separateAllLayerCaches()
@@ -76,13 +69,11 @@ class LayerCache {
7669
}
7770

7871
private async getManifests() {
79-
const manifests = JSON.parse((await fs.readFile(`${this.getUnpackedTarDir()}/manifest.json`)).toString())
80-
assertManifests(manifests)
81-
return manifests
72+
return loadManifests(this.getUnpackedTarDir())
8273
}
8374

8475
private async storeRoot() {
85-
const rootKey = this.getRootKey()
76+
const rootKey = await this.generateRootSaveKey()
8677
const paths = [
8778
this.getUnpackedTarDir(),
8879
]
@@ -143,7 +134,7 @@ class LayerCache {
143134

144135
private async storeSingleLayerBy(id: string): Promise<number> {
145136
const path = this.genSingleLayerStorePath(id)
146-
const key = this.genSingleLayerStoreKey(id)
137+
const key = await this.generateSingleLayerSaveKey(id)
147138

148139
core.info(`Start storing layer cache: ${key}`)
149140
const cacheId = await LayerCache.dismissError(cache.saveCache([path], key), LayerCache.ERROR_CACHE_ALREAD_EXISTS_STR, -1)
@@ -155,8 +146,6 @@ class LayerCache {
155146
// ---
156147

157148
async restore(key: string, restoreKeys?: string[]) {
158-
this.unformattedOrigianlKey = key
159-
// const restoreKeysIncludedRootKey = [key, ...(restoreKeys !== undefined ? restoreKeys : [])]
160149
const restoredCacheKey = await this.restoreRoot(restoreKeys)
161150
if (restoredCacheKey === undefined) {
162151
core.info(`Root cache could not be found. aborting.`)
@@ -175,14 +164,13 @@ class LayerCache {
175164
}
176165

177166
private async restoreRoot(restoreKeys?: string[]): Promise<string | undefined> {
178-
core.debug(`Trying to restore root cache: ${ JSON.stringify({ primaryKey: this.getRootKey(), restoreKeys, dir: this.getUnpackedTarDir() }) }`)
179-
const restoredCacheKeyMayUndefined = await cache.restoreCache([this.getUnpackedTarDir()], this.getRootKey(), restoreKeys)
180-
core.debug(`restoredCacheKeyMayUndefined: ${restoredCacheKeyMayUndefined}`)
181-
if (restoredCacheKeyMayUndefined === undefined) {
167+
core.debug(`Trying to restore root cache: ${ JSON.stringify({ restoreKeys, dir: this.getUnpackedTarDir() }) }`)
168+
const restoredRootKey = await cache.restoreCache([this.getUnpackedTarDir()], ``, restoreKeys)
169+
core.debug(`restoredRootKey: ${restoredRootKey}`)
170+
if (restoredRootKey === undefined) {
182171
return undefined
183172
}
184-
this.restoredOriginalKey = restoredCacheKeyMayUndefined.replace(/-root$/, '')
185-
return this.restoredOriginalKey
173+
this.restoredRootKey = restoredRootKey
186174
}
187175

188176
private async restoreLayers(): Promise<boolean> {
@@ -208,7 +196,7 @@ class LayerCache {
208196
private async restoreSingleLayerBy(id: string): Promise<string> {
209197
core.debug(JSON.stringify({ log: `restoreSingleLayerBy`, id }))
210198

211-
const result = await cache.restoreCache([this.genSingleLayerStorePath(id)], this.genSingleLayerStoreKey(id))
199+
const result = await cache.restoreCache([this.genSingleLayerStorePath(id)], await this.recoverSingleLayerKey(id))
212200

213201
if (result == null) {
214202
throw new Error(`${LayerCache.ERROR_LAYER_CACHE_NOT_FOUND_STR}: ${JSON.stringify({ id })}`)
@@ -247,33 +235,51 @@ class LayerCache {
247235
return 'image'
248236
}
249237

250-
getIdhashesPathFriendly(): string {
251-
const result = crypto.createHash(`sha256`).update(this.ids.join(`-`), `utf8`).digest(`hex`)
238+
async getIdhashesPathFriendly(): Promise<string> {
239+
const result = crypto.createHash(`sha256`).update((await this.getLayerIds()).join(`-`), `utf8`).digest(`hex`)
252240
core.debug(JSON.stringify({ log: `getIdhashesPathFriendly`, result }))
253241
return result
254242
}
255243

256-
getRootKey(): string {
257-
return `${this.getFormattedOriginalCacheKey()}-root`
258-
}
259244

260245
genSingleLayerStorePath(id: string) {
261246
return `${this.getLayerCachesDir()}/${id}/layer.tar`
262247
}
263248

264-
genSingleLayerStoreKey(id: string) {
265-
const singleLayerStoreKey = this.getFormattedOriginalCacheKey(id)
266-
core.debug(JSON.stringify({ log: `genSingleLayerStoreKey`, singleLayerStoreKey, id }))
267-
return `layer-${singleLayerStoreKey}`
249+
async generateRootHashFromManifest(): Promise<string> {
250+
const manifest = await loadRawManifests(this.getUnpackedTarDir())
251+
return crypto.createHash(`sha256`).update(manifest, `utf8`).digest(`hex`)
268252
}
269253

270-
getFormattedOriginalCacheKey(hashThatMayBeSpecified?: string) {
271-
const hash = hashThatMayBeSpecified !== undefined ? hashThatMayBeSpecified : this.getIdhashesPathFriendly()
272-
const result = format(this.unformattedOrigianlKey, { hash })
273-
core.debug(JSON.stringify({ log: `getFormattedOriginalCacheKey`, hash, hashThatMayBeSpecified, result }))
254+
async generateRootSaveKey(): Promise<string> {
255+
const rootHash = await this.generateRootHashFromManifest()
256+
const formatted = await this.getFormattedSaveKey(rootHash)
257+
core.debug(JSON.stringify({ log: `generateRootSaveKey`, rootHash, formatted }))
258+
return `${formatted}-root`
259+
}
260+
261+
async generateSingleLayerSaveKey(id: string) {
262+
const formatted = await this.getFormattedSaveKey(id)
263+
core.debug(JSON.stringify({ log: `generateSingleLayerSaveKey`, formatted, id }))
264+
return `layer-${formatted}`
265+
}
266+
267+
async recoverSingleLayerKey(id: string) {
268+
const unformatted = await this.recoverUnformattedSaveKey()
269+
return format(unformatted, { hash: id })
270+
}
271+
272+
async getFormattedSaveKey(hash: string) {
273+
const result = format(this.unformattedSaveKey, { hash })
274+
core.debug(JSON.stringify({ log: `getFormattedSaveKey`, hash, result }))
274275
return result
275276
}
276277

278+
async recoverUnformattedSaveKey() {
279+
const hash = await loadRawManifests(this.getUnpackedTarDir())
280+
return this.restoredRootKey.replace(hash, `{hash}`)
281+
}
282+
277283
async getLayerTarFiles(): Promise<string[]> {
278284
const getTarFilesFromManifest = (manifest: Manifest) => manifest.Layers
279285

src/Tar.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { assertType } from 'typescript-is'
2+
import { promises as fs } from 'fs'
23

34
export interface Manifest {
45
Config: string
@@ -11,3 +12,13 @@ export type Manifests = Manifest[]
1112
export function assertManifests(x: unknown): asserts x is Manifests {
1213
assertType<Manifests>(x)
1314
}
15+
16+
export async function loadRawManifests(path: string) {
17+
return (await fs.readFile(`${path}/manifests.json`)).toString()
18+
}
19+
export async function loadManifests(path: string) {
20+
const raw = await loadRawManifests(path)
21+
const manifests = JSON.parse(raw.toString())
22+
assertManifests(manifests)
23+
return manifests
24+
}

0 commit comments

Comments
 (0)