Compare commits

...
Sign in to create a new pull request.

39 commits

Author SHA1 Message Date
Alex Rodionov
fd6cff5f63 okay-okay, frontend 2024-06-01 12:50:52 -07:00
Alex Rodionov
09a6cf3bb7 fix 2024-06-01 12:42:08 -07:00
Alex Rodionov
e7b8b2e8f2 back to java 2024-05-31 19:32:28 -07:00
Alex Rodionov
699a0fb94e try frontend 2024-05-31 19:30:29 -07:00
Alex Rodionov
4e82452fc6 try frontend 2024-05-31 19:30:15 -07:00
Alex Rodionov
5137014566 fix bazelisk on wind 2024-05-31 16:30:22 -07:00
Alex Rodionov
64039eff0a print errors 2024-05-31 16:24:11 -07:00
Alex Rodionov
7ab7c614fe fix 2024-05-31 15:51:03 -07:00
Alex Rodionov
99b4749ac7 more 2024-05-31 15:48:01 -07:00
Alex Rodionov
c14694b7be fix 2024-05-31 15:47:25 -07:00
Alex Rodionov
cbd802719f enable windows 2024-05-31 15:45:44 -07:00
Alex Rodionov
44190633ab more 2024-05-31 15:18:21 -07:00
Alex Rodionov
40c9cd5010 more 2024-05-31 15:07:18 -07:00
Alex Rodionov
ddb8388668 info 2024-05-31 15:05:52 -07:00
Alex Rodionov
c77cd78c8b example 2024-05-31 15:01:25 -07:00
Alex Rodionov
cea7755c4f no code mode 2024-05-31 14:59:49 -07:00
Alex Rodionov
c0d204c842 fix 2024-05-31 14:58:35 -07:00
Alex Rodionov
a452639e44 sparse 2024-05-31 14:57:39 -07:00
Alex Rodionov
657484123c don't fail-fast 2024-05-31 08:40:23 -07:00
Alex Rodionov
a36fde6111 log to posix 2024-05-31 08:29:21 -07:00
Alex Rodionov
d683b61ff3 more fix 2024-05-30 20:45:14 -07:00
Alex Rodionov
5cea67652c fix 2024-05-30 20:44:40 -07:00
Alex Rodionov
729d401ac3 refactor 2024-05-30 20:40:48 -07:00
Alex Rodionov
319902179c avoid fork 2024-05-30 18:15:09 -07:00
Alex Rodionov
d5146b7e05 detach 2024-05-30 18:08:23 -07:00
Alex Rodionov
1e86b0e0d9 fix 2024-05-30 16:00:40 -07:00
Alex Rodionov
7d89a268e5 package server 2024-05-30 15:59:24 -07:00
Alex Rodionov
f72666c0ba fix 2024-05-30 15:39:41 -07:00
Alex Rodionov
ad31020598 fix 2024-05-30 15:37:56 -07:00
Alex Rodionov
7ee036d7e7 debug 2024-05-30 15:35:54 -07:00
Alex Rodionov
418a29d1a0 announce 2024-05-30 13:49:50 -07:00
Alex Rodionov
d520205885 fix 2024-05-30 13:47:31 -07:00
Alex Rodionov
ef78fd9c8a build 2024-05-30 13:32:14 -07:00
Alex Rodionov
8883487425
add logs 2024-05-30 13:30:51 -07:00
Alex Rodionov
d47cd4f0b9
explicit target 2024-05-30 13:25:57 -07:00
Alex Rodionov
18922e5162
order of checkout 2024-05-30 13:23:38 -07:00
Alex Rodionov
27731747bb
fix indent 2024-05-30 13:22:42 -07:00
Alex Rodionov
26a4794138
add examples CI 2024-05-30 13:21:40 -07:00
Alex Rodionov
b5e7d0a8af Integrate remote cache server for Bazel 2024-05-30 12:14:52 -07:00
15 changed files with 82271 additions and 18 deletions

View file

@ -13,13 +13,52 @@ jobs:
setup-bazel: setup-bazel:
runs-on: ${{ matrix.os }}-latest runs-on: ${{ matrix.os }}-latest
strategy: strategy:
fail-fast: false
matrix: matrix:
os: os:
- macos - macos
- ubuntu - ubuntu
- windows - windows
steps: steps:
- uses: actions/checkout@v4 - name: Checkout example
- uses: ./ uses: actions/checkout@v4
- if: failure() && runner.debug == '1' with:
repository: bazelbuild/examples
sparse-checkout: frontend
sparse-checkout-cone-mode: false
- name: Checkout setup-bazel
uses: actions/checkout@v4
with:
path: setup-bazel
- name: Prepare environment (POSIX)
if: matrix.os != 'windows'
run: |
rm $(which bazel)
shopt -s dotglob
mv frontend/* .
rmdir frontend
- name: Prepare environment (Windows)
if: matrix.os == 'windows'
run: |
Remove-Item -Path (Get-Command bazel.exe).Source
Get-ChildItem -Path frontend -Recurse -File | Move-Item -Destination .
Remove-Item -Path frontend -Recurse -Force
- name: Setup Bazel
uses: ./setup-bazel/
with:
bazelisk-cache: true
bazelisk-version: 1.x
bazelrc: test --test_output=errors
remote-cache: true
repository-cache: true
- run: bazel build ...
- run: bazel test ...
- name: Start SSH session
if: failure() && runner.debug == '1'
uses: mxschmitt/action-tmate@v3 uses: mxschmitt/action-tmate@v3

View file

@ -29,6 +29,10 @@ inputs:
description: Google Cloud account key for remote cache description: Google Cloud account key for remote cache
required: false required: false
default: "" default: ""
remote-cache:
description: Use built-in remote cache server
required: false
default: "false"
repository-cache: repository-cache:
description: Cache repositories based on MODULE.bazel/WORKSPACE description: Cache repositories based on MODULE.bazel/WORKSPACE
required: false required: false

View file

@ -46,6 +46,16 @@ if (diskCacheEnabled) {
} }
} }
const remoteCacheLogPath = core.toPosixPath(`${os.tmpdir()}/remote-cache-server.log`)
const remoteCacheServerUrl = 'http://localhost:9889/cache'
const remoteCacheEnabled = core.getBooleanInput('remote-cache')
if (remoteCacheEnabled) {
bazelrc.push(`build --remote_cache=${remoteCacheServerUrl}`)
if (diskCacheEnabled) {
core.error('Disk cache and remote cache cannot be enabled at the same time')
}
}
const repositoryCacheConfig = core.getInput('repository-cache') const repositoryCacheConfig = core.getInput('repository-cache')
const repositoryCacheEnabled = repositoryCacheConfig !== 'false' const repositoryCacheEnabled = repositoryCacheConfig !== 'false'
let repositoryCacheFiles = [ let repositoryCacheFiles = [
@ -151,4 +161,9 @@ module.exports = {
name: 'repository', name: 'repository',
paths: [bazelRepository] paths: [bazelRepository]
}, },
remoteCache: {
enabled: remoteCacheEnabled,
logPath: remoteCacheLogPath,
url: remoteCacheServerUrl,
}
} }

60
dist/main/index.js vendored
View file

@ -52,6 +52,16 @@ if (diskCacheEnabled) {
} }
} }
const remoteCacheLogPath = core.toPosixPath(`${os.tmpdir()}/remote-cache-server.log`)
const remoteCacheServerUrl = 'http://localhost:9889/cache'
const remoteCacheEnabled = core.getBooleanInput('remote-cache')
if (remoteCacheEnabled) {
bazelrc.push(`build --remote_cache=${remoteCacheServerUrl}`)
if (diskCacheEnabled) {
core.error('Disk cache and remote cache cannot be enabled at the same time')
}
}
const repositoryCacheConfig = core.getInput('repository-cache') const repositoryCacheConfig = core.getInput('repository-cache')
const repositoryCacheEnabled = repositoryCacheConfig !== 'false' const repositoryCacheEnabled = repositoryCacheConfig !== 'false'
let repositoryCacheFiles = [ let repositoryCacheFiles = [
@ -157,6 +167,11 @@ module.exports = {
name: 'repository', name: 'repository',
paths: [bazelRepository] paths: [bazelRepository]
}, },
remoteCache: {
enabled: remoteCacheEnabled,
logPath: remoteCacheLogPath,
url: remoteCacheServerUrl,
}
} }
@ -96867,6 +96882,8 @@ const github = __nccwpck_require__(5438)
const glob = __nccwpck_require__(8090) const glob = __nccwpck_require__(8090)
const tc = __nccwpck_require__(7784) const tc = __nccwpck_require__(7784)
const config = __nccwpck_require__(5532) const config = __nccwpck_require__(5532)
const { spawn } = __nccwpck_require__(2081)
const path = __nccwpck_require__(1017)
async function run() { async function run() {
try { try {
@ -96889,6 +96906,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() {
@ -96899,7 +96917,7 @@ async function setupBazelisk() {
core.startGroup('Setup Bazelisk') core.startGroup('Setup Bazelisk')
let toolPath = tc.find('bazelisk', config.bazeliskVersion) let toolPath = tc.find('bazelisk', config.bazeliskVersion)
if (toolPath) { if (toolPath) {
core.debug(`Found in cache @ ${toolPath}`) core.info(`Found in cache @ ${toolPath}`)
} else { } else {
toolPath = await downloadBazelisk() toolPath = await downloadBazelisk()
} }
@ -96950,13 +96968,21 @@ async function downloadBazelisk() {
} }
const url = asset.browser_download_url const url = asset.browser_download_url
core.debug(`Downloading from ${url}`) core.info(`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)
core.debug(`Successfully cached bazelisk to ${cachePath}`) let bazelBinName = 'bazel'
let bazeliskBinName = 'bazelisk'
if (platform == 'windows') {
bazelBinName = `${bazelBinName}.exe`
bazeliskBinName = `${bazelBinName}.exe`
}
const cachePath = await tc.cacheFile(downloadPath, bazelBinName, bazeliskBinName, version)
core.info(`Successfully cached bazelisk to ${cachePath}`)
return cachePath return cachePath
} }
@ -97035,6 +97061,28 @@ async function restoreCache(cacheConfig) {
}()) }())
} }
async function startRemoteCacheServer() {
if (!config.remoteCache.enabled) {
return
}
core.startGroup("Start remote cache server")
core.info(`Remote cache server log file path: ${config.remoteCache.logPath}`)
const log = fs.openSync(config.remoteCache.logPath, 'a')
const remoteCacheServer = path.join(__dirname, '..', 'remote-cache-server', 'index.js')
const serverProcess = spawn(process.execPath, [remoteCacheServer], {
detached: true,
stdio: ['ignore', log, log]
})
core.info(`Started remote cache server with PID: ${serverProcess.pid}`)
core.saveState('remote-cache-server-pid', serverProcess.pid.toString())
serverProcess.unref()
core.endGroup()
}
run() run()
})(); })();

File diff suppressed because one or more lines are too long

50
dist/main/remote-cache-server.js vendored Normal file
View 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}`))

40
dist/post/index.js vendored
View file

@ -52,6 +52,16 @@ if (diskCacheEnabled) {
} }
} }
const remoteCacheLogPath = core.toPosixPath(`${os.tmpdir()}/remote-cache-server.log`)
const remoteCacheServerUrl = 'http://localhost:9889/cache'
const remoteCacheEnabled = core.getBooleanInput('remote-cache')
if (remoteCacheEnabled) {
bazelrc.push(`build --remote_cache=${remoteCacheServerUrl}`)
if (diskCacheEnabled) {
core.error('Disk cache and remote cache cannot be enabled at the same time')
}
}
const repositoryCacheConfig = core.getInput('repository-cache') const repositoryCacheConfig = core.getInput('repository-cache')
const repositoryCacheEnabled = repositoryCacheConfig !== 'false' const repositoryCacheEnabled = repositoryCacheConfig !== 'false'
let repositoryCacheFiles = [ let repositoryCacheFiles = [
@ -157,6 +167,11 @@ module.exports = {
name: 'repository', name: 'repository',
paths: [bazelRepository] paths: [bazelRepository]
}, },
remoteCache: {
enabled: remoteCacheEnabled,
logPath: remoteCacheLogPath,
url: remoteCacheServerUrl,
}
} }
@ -95937,9 +95952,34 @@ const config = __nccwpck_require__(5532)
const { getFolderSize } = __nccwpck_require__(4962) const { getFolderSize } = __nccwpck_require__(4962)
async function run() { async function run() {
await stopRemoteCacheServer()
await saveCaches() await saveCaches()
} }
async function stopRemoteCacheServer() {
if (!config.remoteCache.enabled) {
return
}
core.startGroup("Stop remote cache server")
const pid = core.getState('remote-cache-server-pid')
if (pid) {
try {
process.kill(pid, 'SIGTERM')
core.info(`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.remoteCache.logPath
if (fs.existsSync(logPath)) {
const logContent = fs.readFileSync(logPath, 'utf8')
core.debug(`Remote cache server log:\n${logContent}`)
}
core.endGroup()
}
async function saveCaches() { async function saveCaches() {
await saveCache(config.bazeliskCache) await saveCache(config.bazeliskCache)
await saveCache(config.diskCache) await saveCache(config.diskCache)

File diff suppressed because one or more lines are too long

81946
dist/remote-cache-server/index.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/remote-cache-server/index.js.map vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -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 { spawn } = 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() {
@ -38,7 +41,7 @@ async function setupBazelisk() {
core.startGroup('Setup Bazelisk') core.startGroup('Setup Bazelisk')
let toolPath = tc.find('bazelisk', config.bazeliskVersion) let toolPath = tc.find('bazelisk', config.bazeliskVersion)
if (toolPath) { if (toolPath) {
core.debug(`Found in cache @ ${toolPath}`) core.info(`Found in cache @ ${toolPath}`)
} else { } else {
toolPath = await downloadBazelisk() toolPath = await downloadBazelisk()
} }
@ -89,13 +92,21 @@ async function downloadBazelisk() {
} }
const url = asset.browser_download_url const url = asset.browser_download_url
core.debug(`Downloading from ${url}`) core.info(`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)
core.debug(`Successfully cached bazelisk to ${cachePath}`) let bazelBinName = 'bazel'
let bazeliskBinName = 'bazelisk'
if (platform == 'windows') {
bazelBinName = `${bazelBinName}.exe`
bazeliskBinName = `${bazelBinName}.exe`
}
const cachePath = await tc.cacheFile(downloadPath, bazelBinName, bazeliskBinName, version)
core.info(`Successfully cached bazelisk to ${cachePath}`)
return cachePath return cachePath
} }
@ -174,4 +185,26 @@ async function restoreCache(cacheConfig) {
}()) }())
} }
async function startRemoteCacheServer() {
if (!config.remoteCache.enabled) {
return
}
core.startGroup("Start remote cache server")
core.info(`Remote cache server log file path: ${config.remoteCache.logPath}`)
const log = fs.openSync(config.remoteCache.logPath, 'a')
const remoteCacheServer = path.join(__dirname, '..', 'remote-cache-server', 'index.js')
const serverProcess = spawn(process.execPath, [remoteCacheServer], {
detached: true,
stdio: ['ignore', log, log]
})
core.info(`Started remote cache server with PID: ${serverProcess.pid}`)
core.saveState('remote-cache-server-pid', serverProcess.pid.toString())
serverProcess.unref()
core.endGroup()
}
run() run()

View file

@ -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>",

25
post.js
View file

@ -7,9 +7,34 @@ const config = require('./config')
const { getFolderSize } = require('./util') const { getFolderSize } = require('./util')
async function run() { async function run() {
await stopRemoteCacheServer()
await saveCaches() await saveCaches()
} }
async function stopRemoteCacheServer() {
if (!config.remoteCache.enabled) {
return
}
core.startGroup("Stop remote cache server")
const pid = core.getState('remote-cache-server-pid')
if (pid) {
try {
process.kill(pid, 'SIGTERM')
core.info(`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.remoteCache.logPath
if (fs.existsSync(logPath)) {
const logContent = fs.readFileSync(logPath, 'utf8')
core.debug(`Remote cache server log:\n${logContent}`)
}
core.endGroup()
}
async function saveCaches() { async function saveCaches() {
await saveCache(config.bazeliskCache) await saveCache(config.bazeliskCache)
await saveCache(config.diskCache) await saveCache(config.diskCache)

51
remote-cache-server.js Normal file
View file

@ -0,0 +1,51 @@
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 cacheKey = `setup-bazel-1-remote-cache-${sha}`
const filePath = `/tmp/cache-${cacheType}-${sha}`
if (method === 'GET') {
try {
const cacheId = await cache.restoreCache([filePath], cacheKey)
if (!cacheId) {
console.log(`Cache miss for ${cacheKey}`)
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 ${cacheKey}: ${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], cacheKey)
console.log(`Cache saved for ${cacheKey}`)
res.writeHead(201)
res.end('Cache saved')
} catch (error) {
console.error(`Error saving cache for ${cacheKey}: ${error}`)
res.writeHead(500)
res.end('Internal Server Error')
}
})
} else {
res.writeHead(405)
res.end('Method Not Allowed')
}
})
const PORT = process.env.PORT || 9889
server.listen(PORT, () => console.log(`Server listening on port ${PORT}`))