Merge pull request #110 from useblacksmith/move-prune

src: move buildkit prune to cleanup stage and invoke it inline
This commit is contained in:
Aditya Maru 2025-04-22 17:01:26 -04:00 committed by GitHub
commit 550edf2feb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 29 additions and 16 deletions

2
dist/index.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/index.js.map generated vendored

File diff suppressed because one or more lines are too long

View File

@ -20,7 +20,7 @@ import * as context from './context';
import {promisify} from 'util'; import {promisify} from 'util';
import {exec} from 'child_process'; import {exec} from 'child_process';
import * as reporter from './reporter'; import * as reporter from './reporter';
import {setupStickyDisk, startAndConfigureBuildkitd, getNumCPUs, leaveTailnet} from './setup_builder'; import {setupStickyDisk, startAndConfigureBuildkitd, getNumCPUs, leaveTailnet, pruneBuildkitCache} from './setup_builder';
import {Metric_MetricType} from '@buf/blacksmith_vm-agent.bufbuild_es/stickydisk/v1/stickydisk_pb'; import {Metric_MetricType} from '@buf/blacksmith_vm-agent.bufbuild_es/stickydisk/v1/stickydisk_pb';
const buildxVersion = 'v0.17.0'; const buildxVersion = 'v0.17.0';
@ -74,9 +74,9 @@ export async function startBlacksmithBuilder(inputs: context.Inputs): Promise<{a
// If setup-only is true, we don't want to report the build to our control plane // If setup-only is true, we don't want to report the build to our control plane
// since we are only setting up the builder and therefore cannot expose any analytics // since we are only setting up the builder and therefore cannot expose any analytics
// about the build. // about the build.
const dockerfilePath = inputs.setupOnly ? "" : context.getDockerfilePath(inputs); const dockerfilePath = inputs.setupOnly ? '' : context.getDockerfilePath(inputs);
if (!inputs.setupOnly && !dockerfilePath) { if (!inputs.setupOnly && !dockerfilePath) {
throw new Error('Failed to resolve dockerfile path'); throw new Error('Failed to resolve dockerfile path');
} }
const stickyDiskStartTime = Date.now(); const stickyDiskStartTime = Date.now();
const stickyDiskSetup = await setupStickyDisk(dockerfilePath || '', inputs.setupOnly); const stickyDiskSetup = await setupStickyDisk(dockerfilePath || '', inputs.setupOnly);
@ -217,7 +217,6 @@ actionsToolkit.run(
core.warning(`Failed to create builder setup sentinel file: ${error.message}`); core.warning(`Failed to create builder setup sentinel file: ${error.message}`);
} }
let builder: BuilderInfo; let builder: BuilderInfo;
await core.group(`Builder info`, async () => { await core.group(`Builder info`, async () => {
builder = await toolkit.builder.inspect(); builder = await toolkit.builder.inspect();
@ -227,11 +226,10 @@ actionsToolkit.run(
// If setup-only is true, we don't want to continue configuring and running the build. // If setup-only is true, we don't want to continue configuring and running the build.
if (inputs.setupOnly) { if (inputs.setupOnly) {
core.info('setup-only mode enabled, builder is ready for use by Docker'); core.info('setup-only mode enabled, builder is ready for use by Docker');
// Let's remove the default // Let's remove the default
process.exit(0); process.exit(0);
} }
await core.group(`Proxy configuration`, async () => { await core.group(`Proxy configuration`, async () => {
let dockerConfig: ConfigFile | undefined; let dockerConfig: ConfigFile | undefined;
let dockerConfigMalformed = false; let dockerConfigMalformed = false;
@ -362,6 +360,16 @@ actionsToolkit.run(
}); });
} }
// Prune buildkit cache to clean up unused layers before shutting down buildkitd.
try {
core.info('Pruning BuildKit cache');
await pruneBuildkitCache();
core.info('BuildKit cache pruned');
} catch (error) {
// Log warning but don't fail the cleanup
core.warning(`Error pruning BuildKit cache: ${error.message}`);
}
await leaveTailnet(); await leaveTailnet();
try { try {
@ -448,6 +456,16 @@ actionsToolkit.run(
try { try {
const {stdout} = await execAsync('pgrep buildkitd'); const {stdout} = await execAsync('pgrep buildkitd');
if (stdout.trim()) { if (stdout.trim()) {
// Prune buildkit cache to clean up unused layers before shutting down buildkitd.
try {
core.info('Pruning BuildKit cache');
await pruneBuildkitCache();
core.info('BuildKit cache pruned');
} catch (error) {
// Log warning but don't fail the cleanup
core.warning(`Error pruning BuildKit cache: ${error.message}`);
}
await shutdownBuildkitd(); await shutdownBuildkitd();
core.info('Shutdown buildkitd'); core.info('Shutdown buildkitd');
} }

View File

@ -300,16 +300,11 @@ export async function startAndConfigureBuildkitd(parallelism: number, setupOnly:
throw error; throw error;
} }
// Start cache pruning in the background without blocking.
pruneBuildkitCache().catch(error => {
core.warning(`Background cache pruning failed: ${error.message}`);
});
return addr; return addr;
} }
/** /**
* Prunes buildkit cache data older than 14 days. * Prunes buildkit cache data older than 7 days.
* We don't specify any keep bytes here since we are * We don't specify any keep bytes here since we are
* handling the ceph volume size limits ourselves in * handling the ceph volume size limits ourselves in
* the VM Agent. * the VM Agent.
@ -317,8 +312,8 @@ export async function startAndConfigureBuildkitd(parallelism: number, setupOnly:
*/ */
export async function pruneBuildkitCache(): Promise<void> { export async function pruneBuildkitCache(): Promise<void> {
try { try {
const fourteenDaysInHours = 14 * 24; const sevenDaysInHours = 7 * 24;
await execAsync(`sudo buildctl --addr ${BUILDKIT_DAEMON_ADDR} prune --keep-duration ${fourteenDaysInHours}h --all`); await execAsync(`sudo buildctl --addr ${BUILDKIT_DAEMON_ADDR} prune --keep-duration ${sevenDaysInHours}h --all`);
core.debug('Successfully pruned buildkit cache'); core.debug('Successfully pruned buildkit cache');
} catch (error) { } catch (error) {
core.warning(`Error pruning buildkit cache: ${error.message}`); core.warning(`Error pruning buildkit cache: ${error.message}`);