Integrate remote cache server for Bazel
This commit is contained in:
parent
363eb36ada
commit
b5e7d0a8af
5 changed files with 92 additions and 4 deletions
|
|
@ -151,4 +151,9 @@ module.exports = {
|
||||||
name: 'repository',
|
name: 'repository',
|
||||||
paths: [bazelRepository]
|
paths: [bazelRepository]
|
||||||
},
|
},
|
||||||
|
remoteCacheServer: {
|
||||||
|
enabled: true,
|
||||||
|
url: 'http://localhost:8080/cache',
|
||||||
|
logPath: `${os.tmpdir()}/remote-cache-server.log`,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
19
index.js
19
index.js
|
|
@ -6,6 +6,8 @@ const github = require('@actions/github')
|
||||||
const glob = require('@actions/glob')
|
const glob = require('@actions/glob')
|
||||||
const tc = require('@actions/tool-cache')
|
const tc = require('@actions/tool-cache')
|
||||||
const config = require('./config')
|
const config = require('./config')
|
||||||
|
const { fork } = require('child_process')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
try {
|
try {
|
||||||
|
|
@ -28,6 +30,7 @@ async function setupBazel() {
|
||||||
await restoreCache(config.diskCache)
|
await restoreCache(config.diskCache)
|
||||||
await restoreCache(config.repositoryCache)
|
await restoreCache(config.repositoryCache)
|
||||||
await restoreExternalCaches(config.externalCache)
|
await restoreExternalCaches(config.externalCache)
|
||||||
|
await startRemoteCacheServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setupBazelisk() {
|
async function setupBazelisk() {
|
||||||
|
|
@ -92,8 +95,8 @@ async function downloadBazelisk() {
|
||||||
core.debug(`Downloading from ${url}`)
|
core.debug(`Downloading from ${url}`)
|
||||||
const downloadPath = await tc.downloadTool(url, undefined, `token ${token}`)
|
const downloadPath = await tc.downloadTool(url, undefined, `token ${token}`)
|
||||||
|
|
||||||
core.debug('Adding to the cache...');
|
core.debug('Adding to the cache...')
|
||||||
fs.chmodSync(downloadPath, '755');
|
fs.chmodSync(downloadPath, '755')
|
||||||
const cachePath = await tc.cacheFile(downloadPath, 'bazel', 'bazelisk', version)
|
const cachePath = await tc.cacheFile(downloadPath, 'bazel', 'bazelisk', version)
|
||||||
core.debug(`Successfully cached bazelisk to ${cachePath}`)
|
core.debug(`Successfully cached bazelisk to ${cachePath}`)
|
||||||
|
|
||||||
|
|
@ -107,6 +110,7 @@ async function setupBazelrc() {
|
||||||
`startup --output_base=${config.paths.bazelOutputBase}\n`
|
`startup --output_base=${config.paths.bazelOutputBase}\n`
|
||||||
)
|
)
|
||||||
fs.appendFileSync(bazelrcPath, config.bazelrc.join("\n"))
|
fs.appendFileSync(bazelrcPath, config.bazelrc.join("\n"))
|
||||||
|
fs.appendFileSync(bazelrcPath, `build --remote_cache=${config.remoteCacheServer.url}\n`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -174,4 +178,13 @@ async function restoreCache(cacheConfig) {
|
||||||
}())
|
}())
|
||||||
}
|
}
|
||||||
|
|
||||||
run()
|
async function startRemoteCacheServer() {
|
||||||
|
const log = fs.openSync(config.remoteCacheServer.logPath, 'a')
|
||||||
|
const serverProcess = fork(path.join(__dirname, 'dist', 'remote-cache-server', 'index.js'), [], {
|
||||||
|
detached: true,
|
||||||
|
stdio: ['ignore', log, log, 'ipc']
|
||||||
|
})
|
||||||
|
serverProcess.unref()
|
||||||
|
|
||||||
|
core.saveState('remote-cache-server-pid', serverProcess.pid.toString())
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
"node": "20.x"
|
"node": "20.x"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "ncc build index.js -s -o dist/main && ncc build post.js -s -o dist/post",
|
"build": "ncc build index.js -s -o dist/main && ncc build post.js -s -o dist/post && ncc build remote-cache-server.js -s -o dist/remote-cache-server",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
"author": "Alex Rodionov <p0deje@gmail.com>",
|
"author": "Alex Rodionov <p0deje@gmail.com>",
|
||||||
|
|
|
||||||
20
post.js
20
post.js
|
|
@ -5,11 +5,31 @@ const core = require('@actions/core')
|
||||||
const glob = require('@actions/glob')
|
const glob = require('@actions/glob')
|
||||||
const config = require('./config')
|
const config = require('./config')
|
||||||
const { getFolderSize } = require('./util')
|
const { getFolderSize } = require('./util')
|
||||||
|
const { execSync } = require('child_process')
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
|
await stopRemoteCacheServer()
|
||||||
await saveCaches()
|
await saveCaches()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function stopRemoteCacheServer() {
|
||||||
|
const pid = core.getState('remote-cache-server-pid')
|
||||||
|
if (pid) {
|
||||||
|
try {
|
||||||
|
process.kill(pid, 'SIGTERM')
|
||||||
|
core.debug(`Stopped remote cache server with PID: ${pid}`)
|
||||||
|
} catch (error) {
|
||||||
|
core.error(`Failed to stop remote cache server with PID: ${pid}. Error: ${error}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const logPath = config.remoteCacheServer.logPath
|
||||||
|
if (fs.existsSync(logPath)) {
|
||||||
|
const logContent = fs.readFileSync(logPath, 'utf8')
|
||||||
|
core.debug(`Remote cache server log:\n${logContent}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function saveCaches() {
|
async function saveCaches() {
|
||||||
await saveCache(config.bazeliskCache)
|
await saveCache(config.bazeliskCache)
|
||||||
await saveCache(config.diskCache)
|
await saveCache(config.diskCache)
|
||||||
|
|
|
||||||
50
remote-cache-server.js
Normal file
50
remote-cache-server.js
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
const http = require('http')
|
||||||
|
const cache = require('@actions/cache')
|
||||||
|
const fs = require('fs')
|
||||||
|
|
||||||
|
// https://bazel.build/remote/caching#http-caching
|
||||||
|
const server = http.createServer(async (req, res) => {
|
||||||
|
const { method, url } = req
|
||||||
|
const [, , cacheType, sha] = url.split('/')
|
||||||
|
const filePath = `/tmp/cache-${cacheType}-${sha}`
|
||||||
|
|
||||||
|
if (method === 'GET') {
|
||||||
|
try {
|
||||||
|
const cacheId = await cache.restoreCache([filePath], sha)
|
||||||
|
if (!cacheId) {
|
||||||
|
console.log(`Cache miss for ${sha}`)
|
||||||
|
res.writeHead(404)
|
||||||
|
return res.end('Cache miss')
|
||||||
|
}
|
||||||
|
const data = fs.readFileSync(filePath)
|
||||||
|
res.writeHead(200, { 'Content-Type': 'application/octet-stream' })
|
||||||
|
res.end(data)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error retrieving cache for ${sha}: ${error}`)
|
||||||
|
res.writeHead(500)
|
||||||
|
res.end('Internal Server Error')
|
||||||
|
}
|
||||||
|
} else if (method === 'PUT') {
|
||||||
|
const data = []
|
||||||
|
req.on('data', chunk => data.push(chunk))
|
||||||
|
req.on('end', async () => {
|
||||||
|
try {
|
||||||
|
fs.writeFileSync(filePath, Buffer.concat(data))
|
||||||
|
await cache.saveCache([filePath], sha)
|
||||||
|
console.log(`Cache saved for ${sha}`)
|
||||||
|
res.writeHead(201)
|
||||||
|
res.end('Cache saved')
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error saving cache for ${sha}: ${error}`)
|
||||||
|
res.writeHead(500)
|
||||||
|
res.end('Internal Server Error')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
res.writeHead(405)
|
||||||
|
res.end('Method Not Allowed')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const PORT = process.env.PORT || 8080
|
||||||
|
server.listen(PORT, () => console.log(`Server listening on port ${PORT}`))
|
||||||
Loading…
Add table
Add a link
Reference in a new issue