1
0
Fork 0
mirror of https://code.forgejo.org/actions/checkout.git synced 2026-03-08 05:55:49 +00:00

feat: override fetch-depth to 0 when reference-cache is active

When reference-cache is enabled, shallow fetches (fetch-depth > 0) are
counterproductive because objects are served from the local cache.
Shallow negotiation only adds network latency without saving bandwidth.

If fetch-depth was not explicitly set by the user, it is automatically
overridden to 0. If explicitly set, a warning is emitted explaining
the performance impact.

Signed-off-by: Michael Wyraz <mw@brick4u.de>
This commit is contained in:
Michael Wyraz 2026-03-05 15:54:36 +01:00
parent 9ddd3f4b35
commit ed69f3bbdd
6 changed files with 153 additions and 2 deletions

View file

@ -1159,6 +1159,7 @@ async function setup(testName: string): Promise<void> {
sparseCheckout: [],
sparseCheckoutConeMode: true,
fetchDepth: 1,
fetchDepthExplicit: false,
fetchTags: false,
showProgress: true,
lfs: false,

View file

@ -0,0 +1,88 @@
import * as core from '@actions/core'
import {adjustFetchDepthForCache} from '../src/git-source-provider'
// Mock @actions/core
jest.mock('@actions/core')
describe('adjustFetchDepthForCache', () => {
beforeEach(() => {
jest.clearAllMocks()
})
it('does nothing when referenceCache is not set', () => {
const settings = {
referenceCache: '',
fetchDepth: 1,
fetchDepthExplicit: false
}
adjustFetchDepthForCache(settings)
expect(settings.fetchDepth).toBe(1)
expect(core.warning).not.toHaveBeenCalled()
expect(core.info).not.toHaveBeenCalled()
})
it('overrides fetchDepth to 0 when referenceCache is set and fetchDepth is default', () => {
const settings = {
referenceCache: '/cache/git-reference-cache',
fetchDepth: 1,
fetchDepthExplicit: false
}
adjustFetchDepthForCache(settings)
expect(settings.fetchDepth).toBe(0)
expect(core.info).toHaveBeenCalledWith(
expect.stringContaining('Overriding fetch-depth from 1 to 0')
)
expect(core.warning).not.toHaveBeenCalled()
})
it('warns but keeps fetchDepth when referenceCache is set and fetchDepth is explicit', () => {
const settings = {
referenceCache: '/cache/git-reference-cache',
fetchDepth: 1,
fetchDepthExplicit: true
}
adjustFetchDepthForCache(settings)
expect(settings.fetchDepth).toBe(1)
expect(core.warning).toHaveBeenCalledWith(
expect.stringContaining("'fetch-depth: 1' is set with reference-cache enabled")
)
expect(core.info).not.toHaveBeenCalled()
})
it('does nothing when referenceCache is set and fetchDepth is already 0 (explicit)', () => {
const settings = {
referenceCache: '/cache/git-reference-cache',
fetchDepth: 0,
fetchDepthExplicit: true
}
adjustFetchDepthForCache(settings)
expect(settings.fetchDepth).toBe(0)
expect(core.warning).not.toHaveBeenCalled()
expect(core.info).not.toHaveBeenCalled()
})
it('does nothing when referenceCache is set and fetchDepth is already 0 (default)', () => {
const settings = {
referenceCache: '/cache/git-reference-cache',
fetchDepth: 0,
fetchDepthExplicit: false
}
adjustFetchDepthForCache(settings)
expect(settings.fetchDepth).toBe(0)
expect(core.warning).not.toHaveBeenCalled()
expect(core.info).not.toHaveBeenCalled()
})
it('warns with correct depth value when explicit fetchDepth is > 1', () => {
const settings = {
referenceCache: '/cache/git-reference-cache',
fetchDepth: 42,
fetchDepthExplicit: true
}
adjustFetchDepthForCache(settings)
expect(settings.fetchDepth).toBe(42)
expect(core.warning).toHaveBeenCalledWith(
expect.stringContaining("'fetch-depth: 42' is set with reference-cache enabled")
)
})
})

26
dist/index.js vendored
View file

@ -1581,6 +1581,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getSource = getSource;
exports.cleanup = cleanup;
exports.adjustFetchDepthForCache = adjustFetchDepthForCache;
const core = __importStar(__nccwpck_require__(2186));
const fsHelper = __importStar(__nccwpck_require__(7219));
const gitAuthHelper = __importStar(__nccwpck_require__(2565));
@ -1841,6 +1842,9 @@ function getSource(settings) {
if (settings.lfs) {
yield git.lfsInstall();
}
// When using reference cache, fetch-depth > 0 is counterproductive:
// objects are served from the local cache, so shallow negotiation only adds latency.
adjustFetchDepthForCache(settings);
// Fetch
core.startGroup('Fetching the repository');
const fetchOptions = {};
@ -2014,6 +2018,24 @@ function getGitCommandManager(settings) {
}
});
}
/**
* Adjusts fetchDepth when reference-cache is active.
* Shallow fetches are counterproductive with a local cache because
* objects are served from disk, making shallow negotiation pure overhead.
*/
function adjustFetchDepthForCache(settings) {
if (settings.referenceCache && settings.fetchDepth > 0) {
if (settings.fetchDepthExplicit) {
core.warning(`'fetch-depth: ${settings.fetchDepth}' is set with reference-cache enabled. ` +
`This may slow down checkout because shallow negotiation bypasses the local cache. ` +
`Consider using 'fetch-depth: 0' for best performance with reference-cache.`);
}
else {
core.info(`Overriding fetch-depth from ${settings.fetchDepth} to 0 because reference-cache is enabled`);
settings.fetchDepth = 0;
}
}
}
/***/ }),
@ -2374,7 +2396,9 @@ function getInputs() {
(core.getInput('sparse-checkout-cone-mode') || 'true').toUpperCase() ===
'TRUE';
// Fetch depth
result.fetchDepth = Math.floor(Number(core.getInput('fetch-depth') || '1'));
const fetchDepthInput = core.getInput('fetch-depth');
result.fetchDepthExplicit = fetchDepthInput !== '';
result.fetchDepth = Math.floor(Number(fetchDepthInput || '1'));
if (isNaN(result.fetchDepth) || result.fetchDepth < 0) {
result.fetchDepth = 0;
}

View file

@ -335,6 +335,10 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
await git.lfsInstall()
}
// When using reference cache, fetch-depth > 0 is counterproductive:
// objects are served from the local cache, so shallow negotiation only adds latency.
adjustFetchDepthForCache(settings)
// Fetch
core.startGroup('Fetching the repository')
const fetchOptions: {
@ -568,3 +572,30 @@ async function getGitCommandManager(
return undefined
}
}
/**
* Adjusts fetchDepth when reference-cache is active.
* Shallow fetches are counterproductive with a local cache because
* objects are served from disk, making shallow negotiation pure overhead.
*/
export function adjustFetchDepthForCache(
settings: Pick<
IGitSourceSettings,
'referenceCache' | 'fetchDepth' | 'fetchDepthExplicit'
>
): void {
if (settings.referenceCache && settings.fetchDepth > 0) {
if (settings.fetchDepthExplicit) {
core.warning(
`'fetch-depth: ${settings.fetchDepth}' is set with reference-cache enabled. ` +
`This may slow down checkout because shallow negotiation bypasses the local cache. ` +
`Consider using 'fetch-depth: 0' for best performance with reference-cache.`
)
} else {
core.info(
`Overriding fetch-depth from ${settings.fetchDepth} to 0 because reference-cache is enabled`
)
settings.fetchDepth = 0
}
}
}

View file

@ -49,6 +49,11 @@ export interface IGitSourceSettings {
*/
fetchDepth: number
/**
* Whether fetch-depth was explicitly set by the user
*/
fetchDepthExplicit: boolean
/**
* Fetch tags, even if fetchDepth > 0 (default: false)
*/

View file

@ -102,7 +102,9 @@ export async function getInputs(): Promise<IGitSourceSettings> {
'TRUE'
// Fetch depth
result.fetchDepth = Math.floor(Number(core.getInput('fetch-depth') || '1'))
const fetchDepthInput = core.getInput('fetch-depth')
result.fetchDepthExplicit = fetchDepthInput !== ''
result.fetchDepth = Math.floor(Number(fetchDepthInput || '1'))
if (isNaN(result.fetchDepth) || result.fetchDepth < 0) {
result.fetchDepth = 0
}