mirror of
https://github.com/docker/build-push-action.git
synced 2025-08-11 02:52:11 +00:00
refactor: Remove sticky disk management while keeping build reporting
- Remove sticky disk mounting and unmounting logic - Remove sticky disk commit logic from both main and post actions - Replace setupStickyDisk with reportBuildStart to only report build start - Update build completion reporting to not depend on exposeId - Keep build tracking and reporting functionality intact The sticky disk lifecycle is now fully managed by setup-docker-builder
This commit is contained in:
parent
7894682343
commit
877a04de98
2
dist/index.js
generated
vendored
2
dist/index.js
generated
vendored
File diff suppressed because one or more lines are too long
2
dist/index.js.map
generated
vendored
2
dist/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
98
src/main.ts
98
src/main.ts
@ -20,12 +20,11 @@ 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, leaveTailnet} from './setup_builder';
|
import {reportBuildStart, leaveTailnet} 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 DEFAULT_BUILDX_VERSION = 'v0.23.0';
|
const DEFAULT_BUILDX_VERSION = 'v0.23.0';
|
||||||
|
|
||||||
const mountPoint = '/var/lib/buildkit';
|
|
||||||
const execAsync = promisify(exec);
|
const execAsync = promisify(exec);
|
||||||
|
|
||||||
async function retryWithBackoff<T>(operation: () => Promise<T>, maxRetries: number = 5, initialBackoffMs: number = 200): Promise<T> {
|
async function retryWithBackoff<T>(operation: () => Promise<T>, maxRetries: number = 5, initialBackoffMs: number = 200): Promise<T> {
|
||||||
@ -106,10 +105,13 @@ export async function startBlacksmithBuilder(inputs: context.Inputs): Promise<{a
|
|||||||
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 stickyDiskSetup = await setupStickyDisk(dockerfilePath || '', inputs.setupOnly);
|
// Report build start to get a build ID for tracking
|
||||||
const stickyDiskDurationMs = Date.now() - stickyDiskStartTime;
|
let buildId: string | null = null;
|
||||||
await reporter.reportMetric(Metric_MetricType.BPA_HOTLOAD_DURATION_MS, stickyDiskDurationMs);
|
if (!inputs.setupOnly && dockerfilePath) {
|
||||||
|
const buildInfo = await reportBuildStart(dockerfilePath);
|
||||||
|
buildId = buildInfo?.docker_build_id || null;
|
||||||
|
}
|
||||||
|
|
||||||
// For now, we'll check if a builder is already available from setup-docker-builder
|
// For now, we'll check if a builder is already available from setup-docker-builder
|
||||||
// by looking for the sentinel file
|
// by looking for the sentinel file
|
||||||
@ -120,9 +122,8 @@ export async function startBlacksmithBuilder(inputs: context.Inputs): Promise<{a
|
|||||||
throw new Error('Docker builder not available. Please use setup-docker-builder action first.');
|
throw new Error('Docker builder not available. Please use setup-docker-builder action first.');
|
||||||
}
|
}
|
||||||
|
|
||||||
stateHelper.setExposeId(stickyDiskSetup.exposeId);
|
// We no longer manage expose IDs since sticky disk is handled by setup-docker-builder
|
||||||
// Return null for addr since we're not managing the builder anymore
|
return {addr: null, buildId: buildId, exposeId: ''};
|
||||||
return {addr: null, buildId: stickyDiskSetup.buildId || null, exposeId: stickyDiskSetup.exposeId};
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// If the builder setup fails for any reason, we check if we should fallback to a local build.
|
// If the builder setup fails for any reason, we check if we should fallback to a local build.
|
||||||
// If we should not fallback, we rethrow the error and fail the build.
|
// If we should not fallback, we rethrow the error and fail the build.
|
||||||
@ -364,41 +365,13 @@ actionsToolkit.run(
|
|||||||
// Buildkitd is now managed by setup-docker-builder, not here
|
// Buildkitd is now managed by setup-docker-builder, not here
|
||||||
|
|
||||||
await leaveTailnet();
|
await leaveTailnet();
|
||||||
try {
|
// Sticky disk is now managed by setup-docker-builder, not here
|
||||||
// Run sync to flush any pending writes before unmounting.
|
|
||||||
await execAsync('sync');
|
|
||||||
const {stdout: mountOutput} = await execAsync(`mount | grep ${mountPoint}`);
|
|
||||||
if (mountOutput) {
|
|
||||||
for (let attempt = 1; attempt <= 3; attempt++) {
|
|
||||||
try {
|
|
||||||
await execAsync(`sudo umount ${mountPoint}`);
|
|
||||||
core.debug(`${mountPoint} has been unmounted`);
|
|
||||||
break;
|
|
||||||
} catch (error) {
|
|
||||||
if (attempt === 3) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
core.warning(`Unmount failed, retrying (${attempt}/3)...`);
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 100));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
core.info('Unmounted device');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
// grep returns exit code 1 when no matches are found.
|
|
||||||
if (error.code === 1) {
|
|
||||||
core.debug('No dangling mounts found to clean up');
|
|
||||||
} else {
|
|
||||||
// Only warn for actual errors, not for the expected case where grep finds nothing.
|
|
||||||
core.warning(`Error during cleanup: ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builderInfo.addr) {
|
if (builderInfo.buildId) {
|
||||||
if (!buildError) {
|
if (!buildError) {
|
||||||
await reporter.reportBuildCompleted(exportRes, builderInfo.buildId, ref, buildDurationSeconds, builderInfo.exposeId);
|
await reporter.reportBuildCompleted(exportRes, builderInfo.buildId, ref, buildDurationSeconds, '');
|
||||||
} else {
|
} else {
|
||||||
await reporter.reportBuildFailed(builderInfo.buildId, buildDurationSeconds, builderInfo.exposeId);
|
await reporter.reportBuildFailed(builderInfo.buildId, buildDurationSeconds, '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -421,52 +394,13 @@ actionsToolkit.run(
|
|||||||
await leaveTailnet();
|
await leaveTailnet();
|
||||||
|
|
||||||
// Buildkitd is now managed by setup-docker-builder, not here
|
// Buildkitd is now managed by setup-docker-builder, not here
|
||||||
|
// Sticky disk is also managed by setup-docker-builder, not here
|
||||||
|
|
||||||
try {
|
// Clean up temp directory if it exists.
|
||||||
// Run sync to flush any pending writes before unmounting.
|
|
||||||
await execAsync('sync');
|
|
||||||
const {stdout: mountOutput} = await execAsync(`mount | grep ${mountPoint}`);
|
|
||||||
if (mountOutput) {
|
|
||||||
for (let attempt = 1; attempt <= 3; attempt++) {
|
|
||||||
try {
|
|
||||||
await execAsync(`sudo umount ${mountPoint}`);
|
|
||||||
core.debug(`${mountPoint} has been unmounted`);
|
|
||||||
break;
|
|
||||||
} catch (error) {
|
|
||||||
if (attempt === 3) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
core.warning(`Unmount failed, retrying (${attempt}/3)...`);
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 100));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
core.info('Unmounted device');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
if (error.code === 1) {
|
|
||||||
core.debug('No dangling mounts found to clean up');
|
|
||||||
} else {
|
|
||||||
core.warning(`Error during cleanup: ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Clean up temp directory if it exists.
|
|
||||||
if (stateHelper.tmpDir.length > 0) {
|
if (stateHelper.tmpDir.length > 0) {
|
||||||
fs.rmSync(stateHelper.tmpDir, {recursive: true});
|
fs.rmSync(stateHelper.tmpDir, {recursive: true});
|
||||||
core.debug(`Removed temp folder ${stateHelper.tmpDir}`);
|
core.debug(`Removed temp folder ${stateHelper.tmpDir}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. Commit sticky disk if the builder was booted in setup-only mode.
|
|
||||||
// If the builder was not booted in setup-only mode, the sticky disk was committed as part
|
|
||||||
// of the main routine.
|
|
||||||
if (stateHelper.getSetupOnly()) {
|
|
||||||
core.info('Committing sticky disk in post cleanup as setup-only mode was enabled');
|
|
||||||
if (stateHelper.getExposeId() !== '') {
|
|
||||||
await reporter.commitStickyDisk(stateHelper.getExposeId());
|
|
||||||
} else {
|
|
||||||
core.warning('Expose ID not found in state, skipping sticky disk commit');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
core.warning(`Error during final cleanup: ${error.message}`);
|
core.warning(`Error during final cleanup: ${error.message}`);
|
||||||
await reporter.reportBuildPushActionFailure(error, 'final cleanup');
|
await reporter.reportBuildPushActionFailure(error, 'final cleanup');
|
||||||
|
@ -329,6 +329,16 @@ const stickyDiskTimeoutMs = 45000;
|
|||||||
|
|
||||||
// setupStickyDisk mounts a sticky disk for the entity and returns the device information.
|
// setupStickyDisk mounts a sticky disk for the entity and returns the device information.
|
||||||
// throws an error if it is unable to do so because of a timeout or an error
|
// throws an error if it is unable to do so because of a timeout or an error
|
||||||
|
export async function reportBuildStart(dockerfilePath: string): Promise<{docker_build_id: string} | null> {
|
||||||
|
try {
|
||||||
|
const buildResponse = await reporter.reportBuild(dockerfilePath);
|
||||||
|
return buildResponse;
|
||||||
|
} catch (error) {
|
||||||
|
core.warning(`Error reporting build start: ${(error as Error).message}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function setupStickyDisk(dockerfilePath: string, setupOnly: boolean): Promise<{device: string; buildId?: string | null; exposeId: string}> {
|
export async function setupStickyDisk(dockerfilePath: string, setupOnly: boolean): Promise<{device: string; buildId?: string | null; exposeId: string}> {
|
||||||
try {
|
try {
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user