Skip to content

Commit f5aa0f4

Browse files
committed
Make cache prefix configurable, and garbage collect repository cache
1 parent f249a39 commit f5aa0f4

File tree

6 files changed

+63
-112
lines changed

6 files changed

+63
-112
lines changed

README.md

Lines changed: 6 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -85,32 +85,10 @@ Default `""`.
8585

8686
### `disk-cache`
8787

88-
Enable [`disk_cache`][2] and store it on GitHub based on contents of `BUILD` files.
89-
90-
You can also pass a string to use as a cache key to separate caches from different workflows.
88+
Enable [`disk_cache`][2] and store it on GitHub.
9189

9290
Default `false`.
9391

94-
<details>
95-
<summary>Examples</summary>
96-
97-
#### Share a single disk cache
98-
99-
```yaml
100-
- uses: bazel-contrib/[email protected]
101-
with:
102-
disk-cache: true
103-
```
104-
105-
#### Separate disk caches between workflows
106-
107-
```yaml
108-
- uses: bazel-contrib/[email protected]
109-
with:
110-
disk-cache: ${{ github.workflow }}}
111-
```
112-
</details>
113-
11492
### `max-disk-cache-size`
11593

11694
The maximum size, in GB, allowed for the disk cache.
@@ -213,31 +191,16 @@ Default is one of the following:
213191

214192
### `repository-cache`
215193

216-
Enable [`repository_cache`][3] and store it on GitHub based on contents of `MODULE.bazel` and `WORKSPACE` files.
217-
218-
You can also pass a file (or list of files) which contents are used to calculate cache key.
194+
Enable [`repository_cache`][3] and store it on GitHub.
219195

220196
Default `false`.
221197

222-
<details>
223-
<summary>Examples</summary>
224-
225-
#### Store a single repository cache
226-
227-
```yaml
228-
- uses: bazel-contrib/[email protected]
229-
with:
230-
repository-cache: true
231-
```
198+
### `max-repository-cache-size`
232199

233-
#### Store a repository cache from a custom location
200+
The maximum size, in GB, allowed for the repository cache.
201+
Exceeding this size results in garbage collection.
234202

235-
```yaml
236-
- uses: bazel-contrib/[email protected]
237-
with:
238-
repository-cache: examples/gem/WORKSPACE
239-
```
240-
</details>
203+
Default `1`.
241204

242205
## Migrating from [`bazelbuild/setup-bazelisk`][6]
243206

action.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ inputs:
1313
description: Extra contents to write to user .bazelrc
1414
required: false
1515
default: ""
16+
cache-prefix:
17+
description: Key prefix for all caches
18+
required: false
19+
default: ${{ github.job }}-${{ runner.os }}
1620
cache-version:
1721
description: Version of all caches
1822
required: false
@@ -45,6 +49,10 @@ inputs:
4549
description: Cache repositories based on MODULE.bazel/WORKSPACE
4650
required: false
4751
default: "false"
52+
max-repository-cache-size:
53+
description: Maximum repository cache size, in GB
54+
required: false
55+
default: 1
4856
token:
4957
description: GitHub token to query Bazelisk releases
5058
required: false

config.js

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ const core = require('@actions/core')
55
const github = require('@actions/github')
66

77
const bazeliskVersion = core.getInput('bazelisk-version')
8+
const cachePrefix = core.getInput('cache-prefix')
89
const cacheVersion = core.getInput('cache-version')
910
const externalCacheConfig = yaml.parse(core.getInput('external-cache'))
1011
const moduleRoot = core.getInput('module-root')
11-
const maxDiskCacheSize = core.getInput('max-disk-cache-size')
1212

1313
const homeDir = os.homedir()
1414
const arch = os.arch()
@@ -42,32 +42,19 @@ switch (platform) {
4242
break
4343
}
4444

45-
const baseCacheKey = `setup-bazel-${cacheVersion}-${platform}`
45+
const baseCacheKey = `setup-bazel-${cacheVersion}-${cachePrefix}`
4646
const bazelrc = core.getMultilineInput('bazelrc')
4747

48-
const diskCacheConfig = core.getInput('disk-cache')
49-
const diskCacheEnabled = diskCacheConfig !== 'false'
50-
let diskCacheName = 'disk'
48+
const diskCacheEnabled = core.getInput('disk-cache')
49+
const maxDiskCacheSize = core.getInput('max-disk-cache-size')
5150
if (diskCacheEnabled) {
5251
bazelrc.push(`common --disk_cache=${bazelDisk}`)
53-
if (diskCacheName !== 'true') {
54-
diskCacheName = `${diskCacheName}-${diskCacheConfig}`
55-
}
5652
}
5753

58-
const repositoryCacheConfig = core.getInput('repository-cache')
59-
const repositoryCacheEnabled = repositoryCacheConfig !== 'false'
60-
let repositoryCacheFiles = [
61-
`${moduleRoot}/MODULE.bazel`,
62-
`${moduleRoot}/WORKSPACE.bazel`,
63-
`${moduleRoot}/WORKSPACE.bzlmod`,
64-
`${moduleRoot}/WORKSPACE`
65-
]
54+
const repositoryCacheEnabled = core.getInput('repository-cache')
55+
const maxRepositoryCacheSize = core.getInput('max-repository-cache-size')
6656
if (repositoryCacheEnabled) {
6757
bazelrc.push(`common --repository_cache=${bazelRepository}`)
68-
if (repositoryCacheConfig !== 'true') {
69-
repositoryCacheFiles = Array(repositoryCacheConfig).flat()
70-
}
7158
}
7259

7360
const googleCredentials = core.getInput('google-credentials')
@@ -140,12 +127,8 @@ module.exports = {
140127
bazelrc,
141128
diskCache: {
142129
enabled: diskCacheEnabled,
143-
files: [
144-
...repositoryCacheFiles,
145-
`${moduleRoot}/**/BUILD.bazel`,
146-
`${moduleRoot}/**/BUILD`
147-
],
148-
name: diskCacheName,
130+
maxSize: maxDiskCacheSize,
131+
name: 'disk',
149132
paths: [bazelDisk]
150133
},
151134
maxDiskCacheSize,
@@ -161,7 +144,7 @@ module.exports = {
161144
},
162145
repositoryCache: {
163146
enabled: repositoryCacheEnabled,
164-
files: repositoryCacheFiles,
147+
maxSize: maxRepositoryCacheSize,
165148
name: 'repository',
166149
paths: [bazelRepository]
167150
},

gc.js

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,23 @@ const crypto = require('crypto')
22
const fs = require('fs')
33
const path = require('path')
44
const core = require('@actions/core')
5-
const config = require('./config')
65

7-
const diskCachePath = config.diskCache.paths[0]
8-
const diskCacheHash = diskCachePath + '.sha256'
9-
10-
function init() {
11-
if (!config.diskCache.enabled) {
6+
function init(cacheConfig) {
7+
if (!cacheConfig.enabled) {
128
return
139
}
1410

15-
core.startGroup("Computing initial disk cache hash")
16-
fs.writeFileSync(diskCacheHash, computeDiskCacheHash())
11+
core.startGroup(`Computing initial ${cacheConfig.name} cache hash`)
12+
fs.writeFileSync(cacheConfig.path + '.sha256', computeCacheHash(cacheConfig.path))
1713
core.endGroup()
1814
}
1915

20-
function run() {
21-
if (!fs.existsSync(diskCachePath)) {
16+
function run(cacheConfig) {
17+
if (!fs.existsSync(cacheConfig.path)) {
2218
return
2319
}
2420

25-
const files = fs.readdirSync(diskCachePath, { withFileTypes: true, recursive: true })
21+
const files = fs.readdirSync(cacheConfig.path, { withFileTypes: true, recursive: true })
2622
.filter(d => d.isFile())
2723
.map(d => {
2824
const file = path.join(d.path, d.name)
@@ -31,8 +27,8 @@ function run() {
3127
})
3228
.sort((a, b) => b.mtime - a.mtime)
3329

34-
core.startGroup(`Running disk cache garbage collection`)
35-
const deleteThreshold = config.maxDiskCacheSize * 1024 ** 3
30+
core.startGroup(`Running ${cacheConfig.name} cache garbage collection`)
31+
const deleteThreshold = cacheConfig.maxSize * 1024 ** 3
3632
let cacheSize = 0
3733
let reclaimed = 0
3834
for (const { file, size } of files) {
@@ -44,21 +40,24 @@ function run() {
4440
}
4541
core.info(`Reclaimed ${reclaimed} files`)
4642
core.endGroup()
43+
44+
return cacheChanged(cacheConfig)
4745
}
4846

49-
function cacheChanged() {
50-
core.startGroup(`Checking disk cache for changes`)
51-
const changed = fs.readFileSync(diskCacheHash) != computeDiskCacheHash()
47+
function cacheChanged(cacheConfig) {
48+
core.startGroup(`Checking ${cacheConfig.name} cache for changes`)
49+
const hash = computeCacheHash(cacheConfig.path)
50+
const changed = fs.readFileSync(cacheConfig.path + '.sha256') != hash
5251
core.info(`Cache has changes: ${changed}`)
5352
core.endGroup()
54-
return changed
53+
return changed ? hash : undefined
5554
}
5655

57-
function computeDiskCacheHash() {
56+
function computeCacheHash(path) {
5857
let hash = crypto.createHash('sha256')
5958

60-
if (fs.existsSync(diskCachePath)) {
61-
const files = fs.readdirSync(diskCachePath, { withFileTypes: true, recursive: true })
59+
if (fs.existsSync(path)) {
60+
const files = fs.readdirSync(path, { withFileTypes: true, recursive: true })
6261
.filter(d => d.isFile())
6362
.map(d => d.path)
6463
.sort()
@@ -74,5 +73,4 @@ function computeDiskCacheHash() {
7473
module.exports = {
7574
init,
7675
run,
77-
cacheChanged,
7876
}

index.js

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,9 @@ async function setupBazel() {
2626

2727
await setupBazelisk()
2828
await restoreCache(config.bazeliskCache)
29-
await restoreDiskCache(config.diskCache)
30-
await restoreCache(config.repositoryCache)
29+
await restoreGcCache(config.diskCache)
30+
await restoreGcCache(config.repositoryCache)
3131
await restoreExternalCaches(config.externalCache)
32-
33-
gc.init()
3432
}
3533

3634
async function setupBazelisk() {
@@ -186,18 +184,17 @@ async function restoreCache(cacheConfig) {
186184
)
187185
}
188186

189-
async function restoreDiskCache(cacheConfig) {
190-
const hash = await glob.hashFiles(cacheConfig.files.join('\n'))
191-
187+
async function restoreGcCache(cacheConfig) {
192188
// Since disk caches get updated on any change, each run has a unique key.
193189
// Therefore it can only be restored by prefix match, rather than exact key match.
194190
// When multiple prefix matches exist, the most recent is selected.
195191
const restoreKey = `${config.baseCacheKey}-${cacheConfig.name}-`
196-
const hashedRestoreKey = `${restoreKey}${hash}-`
197192
await restoreCacheImpl(
198-
cacheConfig, hashedRestoreKey, [hashedRestoreKey, restoreKey],
193+
cacheConfig, restoreKey, [restoreKey],
199194
restoredKey => restoredKey.startsWith(hashedRestoreKey)
200195
)
196+
197+
gc.init(cacheConfig)
201198
}
202199

203200
run()

post.js

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ async function run() {
1515

1616
async function saveCaches() {
1717
await saveCache(config.bazeliskCache)
18-
await saveDiskCache(config.diskCache)
19-
await saveCache(config.repositoryCache)
18+
await saveGcCache(config.diskCache)
19+
await saveGcCache(config.repositoryCache)
2020
await saveExternalCaches(config.externalCache)
2121
}
2222

@@ -61,26 +61,28 @@ async function saveExternalCaches(cacheConfig) {
6161
}
6262
}
6363

64-
async function saveDiskCache(cacheConfig) {
64+
async function saveGcCache(cacheConfig) {
6565
if (!cacheConfig.enabled) {
6666
return
6767
}
6868

69-
gc.run()
70-
if (!gc.cacheChanged()) {
69+
const hash = gc.run(cacheConfig)
70+
71+
// cache is unchanged
72+
if (!hash) {
73+
return
74+
}
75+
76+
const key = `${config.baseCacheKey}-${cacheConfig.name}-${hash}`
77+
const paths = cacheConfig.paths
78+
79+
// cache already exists
80+
if (await cache.restoreCache(paths, key, [], { lookupOnly: true })) {
7181
return
7282
}
7383

7484
try {
7585
core.startGroup(`Save cache for ${cacheConfig.name}`)
76-
const paths = cacheConfig.paths
77-
const hash = await glob.hashFiles(
78-
cacheConfig.files.join('\n'),
79-
undefined,
80-
// We don't want to follow symlinks as it's extremely slow on macOS.
81-
{ followSymbolicLinks: false }
82-
)
83-
const key = `${config.baseCacheKey}-${cacheConfig.name}-${hash}-${process.env.GITHUB_RUN_ID}.${process.env.GITHUB_RUN_ATTEMPT}`
8486
core.debug(`Attempting to save ${paths} cache to ${key}`)
8587
await cache.saveCache(paths, key)
8688
core.info('Successfully saved cache')

0 commit comments

Comments
 (0)