Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/blacksmith-smoke.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Blacksmith smoke test

on:
workflow_dispatch:
pull_request:

jobs:
smoke:
name: Sticky disk caches on blacksmith runner
runs-on: blacksmith
steps:
- uses: actions/checkout@v4

- name: Assert BLACKSMITH_AGENT_ADDR is advertised
run: test -n "$BLACKSMITH_AGENT_ADDR"

- uses: ./
with:
bazelisk-cache: true

- name: Verify bazelisk cache is a sticky disk mount
run: mountpoint ~/.cache/bazelisk
21 changes: 20 additions & 1 deletion __tests__/restore-cache.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,28 @@ const { loadStickyDisk, setupBazel } = require('../index');

// Mock the stickydisk module
jest.mock('../stickydisk', () => ({
mountStickyDisk: jest.fn()
mountStickyDisk: jest.fn(),
ensureFallbackDirectory: jest.fn()
}));

// Mock the util module: it pulls in the ESM-only generated gRPC client,
// which jest cannot load, and the agent env checks are not under test here.
jest.mock('../util', () => ({
getAgentAddr: jest.fn(() => process.env.BLACKSMITH_AGENT_ADDR || undefined),
getAgentEndpoint: jest.fn(() => {
const addr = process.env.BLACKSMITH_AGENT_ADDR;
const port = process.env.BLACKSMITH_STICKY_DISK_GRPC_PORT;
return addr && port ? `${addr}:${port}` : undefined;
}),
createStickyDiskClient: jest.fn(),
getFolderSize: jest.fn(),
lstatSync: jest.fn()
}));

// Sticky disks require an advertised agent address and gRPC port
process.env.BLACKSMITH_AGENT_ADDR = '192.168.127.1';
process.env.BLACKSMITH_STICKY_DISK_GRPC_PORT = '5557';

// Mock YAML parser
jest.mock('yaml', () => ({
parse: jest.fn().mockImplementation((input) => {
Expand Down
74 changes: 64 additions & 10 deletions dist/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@ const github = __nccwpck_require__(93228)
const glob = __nccwpck_require__(47206)
const tc = __nccwpck_require__(33472)
const config = __nccwpck_require__(50700)
const { mountStickyDisk } = __nccwpck_require__(37220);
const { mountStickyDisk, ensureFallbackDirectory } = __nccwpck_require__(37220);
const { getAgentEndpoint } = __nccwpck_require__(20642);
const crypto = __nccwpck_require__(76982)
const cache = __nccwpck_require__(5116)

Expand Down Expand Up @@ -397,6 +398,16 @@ async function loadStickyDisk(cacheConfig) {
return {};
}

if (!getAgentEndpoint()) {
core.warning(
`BLACKSMITH_AGENT_ADDR or BLACKSMITH_STICKY_DISK_GRPC_PORT is not set; sticky disks are unavailable on this runner. Creating cache directories for ${cacheConfig.name} without persistence.`
);
for (const path of cacheConfig.paths) {
await ensureFallbackDirectory(path);
}
return {};
}

const delay = Math.random() * 1000 // timeout <= 1 sec to reduce contention
const mounts = await setTimeout(delay, async function () {
core.startGroup(`Setting up sticky disk for ${cacheConfig.name}`)
Expand Down Expand Up @@ -435,7 +446,10 @@ async function loadStickyDisk(cacheConfig) {
mount: { device, exposeId, stickyDiskKey: pathKey }
};
} catch (error) {
core.warning(`Failed to mount sticky disk for ${path}: ${error}`);
core.warning(
`Failed to mount sticky disk for ${path}: ${error}. Creating it as a plain directory instead.`
);
await ensureFallbackDirectory(path);
return null;
}
}));
Expand Down Expand Up @@ -45163,6 +45177,20 @@ async function mountStickyDisk(
return { device, exposeId };
}

async function ensureFallbackDirectory(stickyDiskPath) {
try {
await execAsync(`sudo mkdir -p ${stickyDiskPath}`);
await execAsync(`sudo chown $(id -u):$(id -g) ${stickyDiskPath}`);
core.info(
`Sticky disk unavailable; created empty directory at ${stickyDiskPath} (contents will not persist across runs)`,
);
} catch (error) {
core.warning(
`Failed to create fallback directory at ${stickyDiskPath}: ${error}`,
);
}
}

async function commitStickydisk(
exposeId,
stickyDiskKey,
Expand Down Expand Up @@ -45355,6 +45383,7 @@ module.exports = {
getStickyDisk,
maybeFormatBlockDevice,
mountStickyDisk,
ensureFallbackDirectory,
unmountAndCommitStickyDisk,
commitStickydisk,
cleanupStickyDiskWithoutCommit,
Expand All @@ -45377,12 +45406,31 @@ const {
StickyDiskService,
} = __nccwpck_require__(74402);

function getAgentAddr() {
return process.env.BLACKSMITH_AGENT_ADDR || undefined;
}

function getAgentEndpoint() {
const addr = getAgentAddr();
const port = process.env.BLACKSMITH_STICKY_DISK_GRPC_PORT;
if (!addr || !port) {
return undefined;
}
return `${addr}:${port}`;
}

function createStickyDiskClient() {
const port = process.env.BLACKSMITH_STICKY_DISK_GRPC_PORT || "5557";
const addr = getAgentAddr();
const port = process.env.BLACKSMITH_STICKY_DISK_GRPC_PORT;
if (!addr || !port) {
throw new Error(
"BLACKSMITH_AGENT_ADDR or BLACKSMITH_STICKY_DISK_GRPC_PORT is not set; cannot dial the Blacksmith agent",
);
}
const core = __nccwpck_require__(37484);
core.info(`Creating sticky disk client with port ${port}`);
core.info(`Creating sticky disk client for ${addr}:${port}`);
const transport = createGrpcTransport({
baseUrl: `http://192.168.127.1:${port}`,
baseUrl: `http://${addr}:${port}`,
httpVersion: "2",
});

Expand All @@ -45407,21 +45455,21 @@ async function getFolderSize(rootItemPath, options = {}) {
if (typeof directoryItems !== "object") return;
await Promise.all(
directoryItems.map((directoryItem) =>
processItem(path.join(itemPath, directoryItem))
)
processItem(path.join(itemPath, directoryItem)),
),
);
}
}

let folderSize = Array.from(fileSizes.values()).reduce(
(total, fileSize) => total + fileSize,
0n
0n,
);

if (!options.bigint) {
if (folderSize > BigInt(Number.MAX_SAFE_INTEGER)) {
throw new RangeError(
"The folder size is too large to return as a Number. You can instruct this package to return a BigInt instead."
"The folder size is too large to return as a Number. You can instruct this package to return a BigInt instead.",
);
}
folderSize = Number(folderSize);
Expand All @@ -45438,7 +45486,13 @@ function lstatSync(path, opts) {
}
}

module.exports = { createStickyDiskClient, getFolderSize, lstatSync };
module.exports = {
createStickyDiskClient,
getAgentAddr,
getAgentEndpoint,
getFolderSize,
lstatSync,
};


/***/ }),
Expand Down
2 changes: 1 addition & 1 deletion dist/main/index.js.map

Large diffs are not rendered by default.

56 changes: 48 additions & 8 deletions dist/post/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43952,6 +43952,20 @@ async function mountStickyDisk(
return { device, exposeId };
}

async function ensureFallbackDirectory(stickyDiskPath) {
try {
await execAsync(`sudo mkdir -p ${stickyDiskPath}`);
await execAsync(`sudo chown $(id -u):$(id -g) ${stickyDiskPath}`);
core.info(
`Sticky disk unavailable; created empty directory at ${stickyDiskPath} (contents will not persist across runs)`,
);
} catch (error) {
core.warning(
`Failed to create fallback directory at ${stickyDiskPath}: ${error}`,
);
}
}

async function commitStickydisk(
exposeId,
stickyDiskKey,
Expand Down Expand Up @@ -44144,6 +44158,7 @@ module.exports = {
getStickyDisk,
maybeFormatBlockDevice,
mountStickyDisk,
ensureFallbackDirectory,
unmountAndCommitStickyDisk,
commitStickydisk,
cleanupStickyDiskWithoutCommit,
Expand All @@ -44166,12 +44181,31 @@ const {
StickyDiskService,
} = __nccwpck_require__(74402);

function getAgentAddr() {
return process.env.BLACKSMITH_AGENT_ADDR || undefined;
}

function getAgentEndpoint() {
const addr = getAgentAddr();
const port = process.env.BLACKSMITH_STICKY_DISK_GRPC_PORT;
if (!addr || !port) {
return undefined;
}
return `${addr}:${port}`;
}

function createStickyDiskClient() {
const port = process.env.BLACKSMITH_STICKY_DISK_GRPC_PORT || "5557";
const addr = getAgentAddr();
const port = process.env.BLACKSMITH_STICKY_DISK_GRPC_PORT;
if (!addr || !port) {
throw new Error(
"BLACKSMITH_AGENT_ADDR or BLACKSMITH_STICKY_DISK_GRPC_PORT is not set; cannot dial the Blacksmith agent",
);
}
const core = __nccwpck_require__(37484);
core.info(`Creating sticky disk client with port ${port}`);
core.info(`Creating sticky disk client for ${addr}:${port}`);
const transport = createGrpcTransport({
baseUrl: `http://192.168.127.1:${port}`,
baseUrl: `http://${addr}:${port}`,
httpVersion: "2",
});

Expand All @@ -44196,21 +44230,21 @@ async function getFolderSize(rootItemPath, options = {}) {
if (typeof directoryItems !== "object") return;
await Promise.all(
directoryItems.map((directoryItem) =>
processItem(path.join(itemPath, directoryItem))
)
processItem(path.join(itemPath, directoryItem)),
),
);
}
}

let folderSize = Array.from(fileSizes.values()).reduce(
(total, fileSize) => total + fileSize,
0n
0n,
);

if (!options.bigint) {
if (folderSize > BigInt(Number.MAX_SAFE_INTEGER)) {
throw new RangeError(
"The folder size is too large to return as a Number. You can instruct this package to return a BigInt instead."
"The folder size is too large to return as a Number. You can instruct this package to return a BigInt instead.",
);
}
folderSize = Number(folderSize);
Expand All @@ -44227,7 +44261,13 @@ function lstatSync(path, opts) {
}
}

module.exports = { createStickyDiskClient, getFolderSize, lstatSync };
module.exports = {
createStickyDiskClient,
getAgentAddr,
getAgentEndpoint,
getFolderSize,
lstatSync,
};


/***/ }),
Expand Down
2 changes: 1 addition & 1 deletion dist/post/index.js.map

Large diffs are not rendered by default.

Loading
Loading