Compare commits

..

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
21 changed files with 183094 additions and 117216 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@v6 - 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

@ -15,8 +15,8 @@ jobs:
release: release:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
cache: npm cache: npm
node-version-file: package.json node-version-file: package.json

View file

@ -1 +1 @@
nodejs 24.14.0 nodejs 20.14.0

View file

@ -6,7 +6,7 @@ and provides an advanced fine-grained caching to improve workflows performance.
## Usage ## Usage
```yaml ```yaml
- uses: bazel-contrib/setup-bazel@0.18.0 - uses: bazel-contrib/setup-bazel@0.8.4
with: with:
# Avoid downloading Bazel every time. # Avoid downloading Bazel every time.
bazelisk-cache: true bazelisk-cache: true
@ -39,7 +39,7 @@ Default `""`.
#### Install Bazelisk 1.x #### Install Bazelisk 1.x
```yaml ```yaml
- uses: bazel-contrib/setup-bazel@0.18.0 - uses: bazel-contrib/setup-bazel@0.8.4
with: with:
bazelisk-version: 1.x bazelisk-version: 1.x
``` ```
@ -47,7 +47,7 @@ Default `""`.
#### Install exact Bazelisk version #### Install exact Bazelisk version
```yaml ```yaml
- uses: bazel-contrib/setup-bazel@0.18.0 - uses: bazel-contrib/setup-bazel@0.8.4
with: with:
bazelisk-version: 1.19.0 bazelisk-version: 1.19.0
``` ```
@ -67,7 +67,7 @@ Default `""`.
#### Enable Bzlmod #### Enable Bzlmod
```yaml ```yaml
- uses: bazel-contrib/setup-bazel@0.18.0 - uses: bazel-contrib/setup-bazel@0.8.4
with: with:
bazelrc: common --enable_bzlmod bazelrc: common --enable_bzlmod
``` ```
@ -75,7 +75,7 @@ Default `""`.
#### Add colors and timestamps #### Add colors and timestamps
```yaml ```yaml
- uses: bazel-contrib/setup-bazel@0.18.0 - uses: bazel-contrib/setup-bazel@0.8.4
with: with:
bazelrc: | bazelrc: |
build --color=yes build --color=yes
@ -83,30 +83,6 @@ Default `""`.
``` ```
</details> </details>
### `cache-save`
Whether to save caches at the end of the workflow.
Set to `false` for pull requests to allow cache restoration without saving,
which prevents PRs from polluting the cache while still benefiting from it.
Default `true`.
<details>
<summary>Examples</summary>
#### Disable cache saving on pull requests
```yaml
- uses: bazel-contrib/setup-bazel@0.18.0
with:
bazelisk-cache: true
disk-cache: ${{ github.workflow }}
repository-cache: true
cache-save: ${{ github.event_name != 'pull_request' }}
```
</details>
### `disk-cache` ### `disk-cache`
Enable [`disk_cache`][2] and store it on GitHub based on contents of `BUILD` files. Enable [`disk_cache`][2] and store it on GitHub based on contents of `BUILD` files.
@ -121,7 +97,7 @@ Default `false`.
#### Share a single disk cache #### Share a single disk cache
```yaml ```yaml
- uses: bazel-contrib/setup-bazel@0.18.0 - uses: bazel-contrib/setup-bazel@0.8.4
with: with:
disk-cache: true disk-cache: true
``` ```
@ -129,9 +105,9 @@ Default `false`.
#### Separate disk caches between workflows #### Separate disk caches between workflows
```yaml ```yaml
- uses: bazel-contrib/setup-bazel@0.18.0 - uses: bazel-contrib/setup-bazel@0.8.4
with: with:
disk-cache: ${{ github.workflow }} disk-cache: ${{ github.workflow }}}
``` ```
</details> </details>
@ -153,7 +129,7 @@ Default `false`.
#### Enable external repositories caches #### Enable external repositories caches
```yaml ```yaml
- uses: bazel-contrib/setup-bazel@0.18.0 - uses: bazel-contrib/setup-bazel@0.8.4
with: with:
external-cache: true external-cache: true
``` ```
@ -161,7 +137,7 @@ Default `false`.
#### Cache NPM repositories based on `package-lock.json` contents #### Cache NPM repositories based on `package-lock.json` contents
```yaml ```yaml
- uses: bazel-contrib/setup-bazel@0.18.0 - uses: bazel-contrib/setup-bazel@0.8.4
with: with:
external-cache: | external-cache: |
manifest: manifest:
@ -171,7 +147,7 @@ Default `false`.
#### Do not cache Ruby on Windows #### Do not cache Ruby on Windows
```yaml ```yaml
- uses: bazel-contrib/setup-bazel@0.18.0 - uses: bazel-contrib/setup-bazel@0.8.4
with: with:
external-cache: | external-cache: |
manifest: manifest:
@ -191,42 +167,12 @@ Default `""`.
#### Authenticate via key #### Authenticate via key
```yaml ```yaml
- uses: bazel-contrib/setup-bazel@0.18.0 - uses: bazel-contrib/setup-bazel@0.8.4
with: with:
google-credentials: ${{ secrets.GOOGLE_CLOUD_KEY }} google-credentials: ${{ secrets.GOOGLE_CLOUD_KEY }}
``` ```
</details> </details>
### `module-root`
Bazel module root directory, where `MODULE.bazel` and `WORKSPACE` is found.
Change this value to the module root if it's not the repository root.
Default `"."`.
### `output-base`
Change Bazel output base directory.
You might want to change it when running on self-hosted runners with a custom directory layout.
Default is one of the following:
- `$HOME/.bazel` on Linux and macOS
- `D:/_bazel` on Windows
<details>
<summary>Examples</summary>
#### Use `C` drive letter
```yaml
- uses: bazel-contrib/setup-bazel@0.18.0
with:
output-base: C:/_bazel
```
</details>
### `repository-cache` ### `repository-cache`
@ -242,7 +188,7 @@ Default `false`.
#### Store a single repository cache #### Store a single repository cache
```yaml ```yaml
- uses: bazel-contrib/setup-bazel@0.18.0 - uses: bazel-contrib/setup-bazel@0.8.4
with: with:
repository-cache: true repository-cache: true
``` ```
@ -250,19 +196,10 @@ Default `false`.
#### Store a repository cache from a custom location #### Store a repository cache from a custom location
```yaml ```yaml
- uses: bazel-contrib/setup-bazel@0.18.0 - uses: bazel-contrib/setup-bazel@0.8.4
with: with:
repository-cache: examples/gem/WORKSPACE repository-cache: examples/gem/WORKSPACE
``` ```
#### Store a repository cache from a list of custom locations
```yaml
- uses: bazel-contrib/setup-bazel@0.18.0
with:
repository-cache: |
- MODULE.bazel
- requirements_locked.txt
```
</details> </details>
## Migrating from [`bazelbuild/setup-bazelisk`][6] ## Migrating from [`bazelbuild/setup-bazelisk`][6]
@ -276,7 +213,6 @@ However, if you used a `bazel-version` input before, you will need to remove it
To build action, run the following command: To build action, run the following command:
```sh ```sh
$ npm install
$ npm run build $ npm run build
``` ```

View file

@ -13,10 +13,6 @@ inputs:
description: Extra contents to write to user .bazelrc description: Extra contents to write to user .bazelrc
required: false required: false
default: "" default: ""
cache-save:
description: Whether to save caches. Set to false for pull requests to allow restores but prevent saves.
required: false
default: "true"
cache-version: cache-version:
description: Version of all caches description: Version of all caches
required: false required: false
@ -33,14 +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: ""
module-root: remote-cache:
description: Bazel module root directory. Default is `.` description: Use built-in remote cache server
required: false required: false
default: "." default: "false"
output-base:
description: Bazel output base directory. Default is $HOME/.cache/bazel (POSIX) or D:/_bazel (Windows)
required: false
default: ""
repository-cache: repository-cache:
description: Cache repositories based on MODULE.bazel/WORKSPACE description: Cache repositories based on MODULE.bazel/WORKSPACE
required: false required: false
@ -54,4 +46,3 @@ runs:
using: node20 using: node20
main: dist/main/index.js main: dist/main/index.js
post: dist/post/index.js post: dist/post/index.js
post-if: "!cancelled()"

View file

@ -5,30 +5,16 @@ const core = require('@actions/core')
const github = require('@actions/github') const github = require('@actions/github')
const bazeliskVersion = core.getInput('bazelisk-version') const bazeliskVersion = core.getInput('bazelisk-version')
const cacheSave = core.getBooleanInput('cache-save')
const cacheVersion = core.getInput('cache-version') const cacheVersion = core.getInput('cache-version')
const moduleRoot = core.getInput('module-root') const externalCacheConfig = yaml.parse(core.getInput('external-cache'))
const homeDir = os.homedir() const homeDir = os.homedir()
const arch = os.arch() const arch = os.arch()
const platform = os.platform() const platform = os.platform()
let bazelOutputBase = core.getInput('output-base')
if (!bazelOutputBase) {
if (platform === 'win32') {
// check if GITHUB_WORKSPACE starts with D:
if (process.env.GITHUB_WORKSPACE?.toLowerCase()?.startsWith('d:')) {
bazelOutputBase = 'D:/_bazel'
} else {
bazelOutputBase = `C:/_bazel`
}
} else {
bazelOutputBase = `${homeDir}/.bazel`
}
}
let bazelDisk = core.toPosixPath(`${homeDir}/.cache/bazel-disk`) let bazelDisk = core.toPosixPath(`${homeDir}/.cache/bazel-disk`)
let bazelRepository = core.toPosixPath(`${homeDir}/.cache/bazel-repo`) let bazelRepository = core.toPosixPath(`${homeDir}/.cache/bazel-repo`)
let bazelOutputBase = `${homeDir}/.bazel`
let bazelrcPaths = [core.toPosixPath(`${homeDir}/.bazelrc`)] let bazelrcPaths = [core.toPosixPath(`${homeDir}/.bazelrc`)]
let userCacheDir = `${homeDir}/.cache` let userCacheDir = `${homeDir}/.cache`
@ -37,8 +23,9 @@ switch (platform) {
userCacheDir = `${homeDir}/Library/Caches` userCacheDir = `${homeDir}/Library/Caches`
break break
case 'win32': case 'win32':
bazelDisk = `${bazelOutputBase}-disk` bazelDisk = 'D:/_bazel-disk'
bazelRepository = `${bazelOutputBase}-repo` bazelRepository = 'D:/_bazel-repo'
bazelOutputBase = 'D:/_bazel'
userCacheDir = `${homeDir}/AppData/Local` userCacheDir = `${homeDir}/AppData/Local`
if (process.env.HOME) { if (process.env.HOME) {
bazelrcPaths.push(core.toPosixPath(`${process.env.HOME}/.bazelrc`)) bazelrcPaths.push(core.toPosixPath(`${process.env.HOME}/.bazelrc`))
@ -46,33 +33,40 @@ switch (platform) {
break break
} }
const baseCacheKey = `setup-bazel-${cacheVersion}-${platform}-${arch}` const baseCacheKey = `setup-bazel-${cacheVersion}-${platform}`
const bazelrc = core.getMultilineInput('bazelrc') const bazelrc = core.getMultilineInput('bazelrc')
const diskCacheConfig = core.getInput('disk-cache') const diskCacheConfig = core.getInput('disk-cache')
const diskCacheEnabled = diskCacheConfig !== 'false' const diskCacheEnabled = diskCacheConfig !== 'false'
let diskCacheName = 'disk' let diskCacheName = 'disk'
if (diskCacheEnabled) { if (diskCacheEnabled) {
// Before Bazel 6.3, providing --disk_cache to common is an error,
// with Bazel 6.3 and onwards, common accepts any legal Bazel option
// https://github.com/bazelbuild/bazel/issues/3054
bazelrc.push(`build --disk_cache=${bazelDisk}`) bazelrc.push(`build --disk_cache=${bazelDisk}`)
if (diskCacheName !== 'true') { if (diskCacheName !== 'true') {
diskCacheName = `${diskCacheName}-${diskCacheConfig}` diskCacheName = `${diskCacheName}-${diskCacheConfig}`
} }
} }
const repositoryCacheConfig = yaml.parse(core.getInput('repository-cache')) const remoteCacheLogPath = core.toPosixPath(`${os.tmpdir()}/remote-cache-server.log`)
const repositoryCacheEnabled = repositoryCacheConfig !== false 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 repositoryCacheEnabled = repositoryCacheConfig !== 'false'
let repositoryCacheFiles = [ let repositoryCacheFiles = [
`${moduleRoot}/MODULE.bazel`, 'MODULE.bazel',
`${moduleRoot}/WORKSPACE.bazel`, 'WORKSPACE.bazel',
`${moduleRoot}/WORKSPACE.bzlmod`, 'WORKSPACE.bzlmod',
`${moduleRoot}/WORKSPACE` 'WORKSPACE'
] ]
if (repositoryCacheEnabled) { if (repositoryCacheEnabled) {
bazelrc.push(`common --repository_cache=${bazelRepository}`) bazelrc.push(`build --repository_cache=${bazelRepository}`)
if (repositoryCacheConfig !== true) { if (repositoryCacheConfig !== 'true') {
repositoryCacheFiles = Array(repositoryCacheConfig).flat() repositoryCacheFiles = Array(repositoryCacheConfig).flat()
} }
} }
@ -80,14 +74,13 @@ if (repositoryCacheEnabled) {
const googleCredentials = core.getInput('google-credentials') const googleCredentials = core.getInput('google-credentials')
const googleCredentialsSaved = (core.getState('google-credentials-path').length > 0) const googleCredentialsSaved = (core.getState('google-credentials-path').length > 0)
if (googleCredentials.length > 0 && !googleCredentialsSaved) { if (googleCredentials.length > 0 && !googleCredentialsSaved) {
const tmpDir = core.toPosixPath(fs.mkdtempSync(process.env.RUNNER_TEMP)) const tmpDir = core.toPosixPath(fs.mkdtempSync(os.tmpdir()))
const googleCredentialsPath = `${tmpDir}/key.json` const googleCredentialsPath = `${tmpDir}/key.json`
fs.writeFileSync(googleCredentialsPath, googleCredentials) fs.writeFileSync(googleCredentialsPath, googleCredentials)
bazelrc.push(`build --google_credentials=${googleCredentialsPath}`) bazelrc.push(`build --google_credentials=${googleCredentialsPath}`)
core.saveState('google-credentials-path', googleCredentialsPath) core.saveState('google-credentials-path', googleCredentialsPath)
} }
const externalCacheConfig = yaml.parse(core.getInput('external-cache'))
const bazelExternal = core.toPosixPath(`${bazelOutputBase}/external`) const bazelExternal = core.toPosixPath(`${bazelOutputBase}/external`)
const externalCache = {} const externalCache = {}
if (externalCacheConfig) { if (externalCacheConfig) {
@ -100,10 +93,10 @@ if (externalCacheConfig) {
externalCache.baseCacheKey = `${baseCacheKey}-external-` externalCache.baseCacheKey = `${baseCacheKey}-external-`
externalCache.manifest = { externalCache.manifest = {
files: [ files: [
`${moduleRoot}/MODULE.bazel`, 'MODULE.bazel',
`${moduleRoot}/WORKSPACE.bazel`, 'WORKSPACE.bazel',
`${moduleRoot}/WORKSPACE.bzlmod`, 'WORKSPACE.bzlmod',
`${moduleRoot}/WORKSPACE` 'WORKSPACE'
], ],
name: `external-${manifestName}-manifest`, name: `external-${manifestName}-manifest`,
path: `${os.tmpdir()}/external-cache-manifest.txt` path: `${os.tmpdir()}/external-cache-manifest.txt`
@ -111,10 +104,10 @@ if (externalCacheConfig) {
externalCache.default = { externalCache.default = {
enabled: true, enabled: true,
files: [ files: [
`${moduleRoot}/MODULE.bazel`, 'MODULE.bazel',
`${moduleRoot}/WORKSPACE.bazel`, 'WORKSPACE.bazel',
`${moduleRoot}/WORKSPACE.bzlmod`, 'WORKSPACE.bzlmod',
`${moduleRoot}/WORKSPACE` 'WORKSPACE'
], ],
name: (name) => { return `external-${name}` }, name: (name) => { return `external-${name}` },
paths: (name) => { paths: (name) => {
@ -133,15 +126,11 @@ if (externalCacheConfig) {
} }
} }
const token = core.getInput('token')
core.exportVariable('BAZELISK_GITHUB_TOKEN', token)
module.exports = { module.exports = {
baseCacheKey, baseCacheKey,
cacheSave,
bazeliskCache: { bazeliskCache: {
enabled: core.getBooleanInput('bazelisk-cache'), enabled: core.getBooleanInput('bazelisk-cache'),
files: [`${moduleRoot}/.bazelversion`], files: ['.bazelversion'],
name: 'bazelisk', name: 'bazelisk',
paths: [core.toPosixPath(`${userCacheDir}/bazelisk`)] paths: [core.toPosixPath(`${userCacheDir}/bazelisk`)]
}, },
@ -150,9 +139,8 @@ module.exports = {
diskCache: { diskCache: {
enabled: diskCacheEnabled, enabled: diskCacheEnabled,
files: [ files: [
...repositoryCacheFiles, '**/BUILD.bazel',
`${moduleRoot}/**/BUILD.bazel`, '**/BUILD'
`${moduleRoot}/**/BUILD`
], ],
name: diskCacheName, name: diskCacheName,
paths: [bazelDisk] paths: [bazelDisk]
@ -173,4 +161,9 @@ module.exports = {
name: 'repository', name: 'repository',
paths: [bazelRepository] paths: [bazelRepository]
}, },
remoteCache: {
enabled: remoteCacheEnabled,
logPath: remoteCacheLogPath,
url: remoteCacheServerUrl,
}
} }

109683
dist/main/index.js vendored

File diff suppressed because one or more lines are too long

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}`))

File diff suppressed because one or more lines are too long

107184
dist/post/index.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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()
} }
@ -69,10 +72,8 @@ async function downloadBazelisk() {
filename = `${filename}.exe` filename = `${filename}.exe`
} }
const token = process.env.BAZELISK_GITHUB_TOKEN const token = core.getInput('token')
const octokit = github.getOctokit(token, { const octokit = github.getOctokit(token)
baseUrl: 'https://api.github.com'
})
const { data: releases } = await octokit.rest.repos.listReleases({ const { data: releases } = await octokit.rest.repos.listReleases({
owner: 'bazelbuild', owner: 'bazelbuild',
repo: 'bazelisk' repo: 'bazelisk'
@ -91,17 +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')
let bazel_name = "bazel";
let bazelBinName = 'bazel'
let bazeliskBinName = 'bazelisk'
if (platform == 'windows') { if (platform == 'windows') {
bazel_name = `${bazel_name}.exe` bazelBinName = `${bazelBinName}.exe`
bazeliskBinName = `${bazelBinName}.exe`
} }
const cachePath = await tc.cacheFile(downloadPath, bazel_name, 'bazelisk', version)
core.debug(`Successfully cached bazelisk to ${cachePath}`) const cachePath = await tc.cacheFile(downloadPath, bazelBinName, bazeliskBinName, version)
core.info(`Successfully cached bazelisk to ${cachePath}`)
return cachePath return cachePath
} }
@ -133,16 +138,14 @@ async function restoreExternalCaches(cacheConfig) {
// Now restore all external caches defined in manifest // Now restore all external caches defined in manifest
if (fs.existsSync(path)) { if (fs.existsSync(path)) {
const manifest = fs.readFileSync(path, { encoding: 'utf8' }) const manifest = fs.readFileSync(path, { encoding: 'utf8' })
const restorePromises = manifest.split('\n').filter(s => s) for (const name of manifest.split('\n').filter(s => s)) {
.map(name => { await restoreCache({
return restoreCache({ enabled: cacheConfig[name]?.enabled ?? cacheConfig.default.enabled,
enabled: cacheConfig[name]?.enabled ?? cacheConfig.default.enabled, files: cacheConfig[name]?.files || cacheConfig.default.files,
files: cacheConfig[name]?.files || cacheConfig.default.files, name: cacheConfig.default.name(name),
name: cacheConfig.default.name(name), paths: cacheConfig.default.paths(name)
paths: cacheConfig.default.paths(name) })
}); }
});
await Promise.all(restorePromises);
} }
} }
@ -152,10 +155,9 @@ async function restoreCache(cacheConfig) {
} }
const delay = Math.random() * 1000 // timeout <= 1 sec to reduce 429 errors const delay = Math.random() * 1000 // timeout <= 1 sec to reduce 429 errors
await setTimeout(delay) await setTimeout(delay, async function () {
core.startGroup(`Restore cache for ${cacheConfig.name}`)
core.startGroup(`Restore cache for ${cacheConfig.name}`)
try {
const hash = await glob.hashFiles(cacheConfig.files.join('\n')) const hash = await glob.hashFiles(cacheConfig.files.join('\n'))
const name = cacheConfig.name const name = cacheConfig.name
const paths = cacheConfig.paths const paths = cacheConfig.paths
@ -178,11 +180,31 @@ async function restoreCache(cacheConfig) {
} else { } else {
core.info(`Failed to restore ${name} cache`) core.info(`Failed to restore ${name} cache`)
} }
} catch (err) {
core.warning(`Failed to restore ${name} cache with error: ${err}`)
} finally {
core.endGroup() core.endGroup()
}())
}
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()

1017
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,23 +1,23 @@
{ {
"name": "setup-bazel", "name": "setup-bazel",
"version": "0.18.0", "version": "0.8.4",
"description": "Install and configure Bazel for GitHub Actions", "description": "Install and configure Bazel for GitHub Actions",
"main": "index.js", "main": "index.js",
"engines": { "engines": {
"node": "24.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>",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/cache": "^6.0.0", "@actions/cache": "^3.2.2",
"@actions/core": "^3.0.0", "@actions/core": "^1.10.1",
"@actions/github": "^9.0.0", "@actions/github": "^6.0.0",
"@actions/glob": "^0.6.0", "@actions/glob": "^0.4.0",
"@actions/tool-cache": "^4.0.0", "@actions/tool-cache": "^2.0.1",
"@vercel/ncc": "^0.38.0", "@vercel/ncc": "^0.38.0",
"yaml": "^2.2.1" "yaml": "^2.2.1"
} }

28
post.js
View file

@ -5,19 +5,37 @@ 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 process = require('node:process');
async function run() { async function run() {
await stopRemoteCacheServer()
await saveCaches() await saveCaches()
process.exit(0)
} }
async function saveCaches() { async function stopRemoteCacheServer() {
if (!config.cacheSave) { if (!config.remoteCache.enabled) {
core.info('Cache saving is disabled (cache-save: false)')
return 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() {
await saveCache(config.bazeliskCache) await saveCache(config.bazeliskCache)
await saveCache(config.diskCache) await saveCache(config.diskCache)
await saveCache(config.repositoryCache) await saveCache(config.repositoryCache)

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}`))