mirror of
https://github.com/actions/checkout.git
synced 2026-03-19 02:49:07 +00:00
Add configurable timeout and retry for git network operations
Add per-attempt timeout (default 300s) and Kubernetes probe-style retry configuration for git fetch, lfs-fetch, and ls-remote. New action inputs: timeout, retry-max-attempts, retry-min-backoff, retry-max-backoff. Fixes https://github.com/actions/checkout/issues/631 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
0c366fd6a8
commit
5df58a66d1
22
README.md
22
README.md
@ -155,6 +155,28 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/
|
|||||||
# Default: true
|
# Default: true
|
||||||
set-safe-directory: ''
|
set-safe-directory: ''
|
||||||
|
|
||||||
|
# Timeout in seconds for each git network operation attempt (fetch, lfs-fetch,
|
||||||
|
# ls-remote). If a single attempt exceeds this, it is killed and retried. Set to 0
|
||||||
|
# to disable. Default is 300 (5 minutes). Similar to Kubernetes probe
|
||||||
|
# timeoutSeconds.
|
||||||
|
# Default: 300
|
||||||
|
timeout: ''
|
||||||
|
|
||||||
|
# Maximum number of retry attempts for failed git network operations. Similar to
|
||||||
|
# Kubernetes probe failureThreshold.
|
||||||
|
# Default: 3
|
||||||
|
retry-max-attempts: ''
|
||||||
|
|
||||||
|
# Minimum backoff time in seconds between retry attempts. The actual backoff is
|
||||||
|
# randomly chosen between min and max. Similar to Kubernetes probe periodSeconds.
|
||||||
|
# Default: 10
|
||||||
|
retry-min-backoff: ''
|
||||||
|
|
||||||
|
# Maximum backoff time in seconds between retry attempts. The actual backoff is
|
||||||
|
# randomly chosen between min and max.
|
||||||
|
# Default: 20
|
||||||
|
retry-max-backoff: ''
|
||||||
|
|
||||||
# The base URL for the GitHub instance that you are trying to clone from, will use
|
# The base URL for the GitHub instance that you are trying to clone from, will use
|
||||||
# environment defaults to fetch from the same instance that the workflow is
|
# environment defaults to fetch from the same instance that the workflow is
|
||||||
# running from unless specified. Example URLs are https://github.com or
|
# running from unless specified. Example URLs are https://github.com or
|
||||||
|
|||||||
@ -1146,7 +1146,9 @@ async function setup(testName: string): Promise<void> {
|
|||||||
}
|
}
|
||||||
),
|
),
|
||||||
tryReset: jest.fn(),
|
tryReset: jest.fn(),
|
||||||
version: jest.fn()
|
version: jest.fn(),
|
||||||
|
setTimeout: jest.fn(),
|
||||||
|
setRetryConfig: jest.fn()
|
||||||
}
|
}
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
@ -1173,7 +1175,11 @@ async function setup(testName: string): Promise<void> {
|
|||||||
sshUser: '',
|
sshUser: '',
|
||||||
workflowOrganizationId: 123456,
|
workflowOrganizationId: 123456,
|
||||||
setSafeDirectory: true,
|
setSafeDirectory: true,
|
||||||
githubServerUrl: githubServerUrl
|
githubServerUrl: githubServerUrl,
|
||||||
|
timeout: 300,
|
||||||
|
retryMaxAttempts: 3,
|
||||||
|
retryMinBackoff: 10,
|
||||||
|
retryMaxBackoff: 20
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -506,6 +506,8 @@ async function setup(testName: string): Promise<void> {
|
|||||||
tryReset: jest.fn(async () => {
|
tryReset: jest.fn(async () => {
|
||||||
return true
|
return true
|
||||||
}),
|
}),
|
||||||
version: jest.fn()
|
version: jest.fn(),
|
||||||
|
setTimeout: jest.fn(),
|
||||||
|
setRetryConfig: jest.fn()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
23
action.yml
23
action.yml
@ -95,6 +95,29 @@ inputs:
|
|||||||
set-safe-directory:
|
set-safe-directory:
|
||||||
description: Add repository path as safe.directory for Git global config by running `git config --global --add safe.directory <path>`
|
description: Add repository path as safe.directory for Git global config by running `git config --global --add safe.directory <path>`
|
||||||
default: true
|
default: true
|
||||||
|
timeout:
|
||||||
|
description: >
|
||||||
|
Timeout in seconds for each git network operation attempt (fetch, lfs-fetch, ls-remote).
|
||||||
|
If a single attempt exceeds this, it is killed and retried.
|
||||||
|
Set to 0 to disable. Default is 300 (5 minutes).
|
||||||
|
Similar to Kubernetes probe timeoutSeconds.
|
||||||
|
default: 300
|
||||||
|
retry-max-attempts:
|
||||||
|
description: >
|
||||||
|
Maximum number of retry attempts for failed git network operations.
|
||||||
|
Similar to Kubernetes probe failureThreshold.
|
||||||
|
default: 3
|
||||||
|
retry-min-backoff:
|
||||||
|
description: >
|
||||||
|
Minimum backoff time in seconds between retry attempts.
|
||||||
|
The actual backoff is randomly chosen between min and max.
|
||||||
|
Similar to Kubernetes probe periodSeconds.
|
||||||
|
default: 10
|
||||||
|
retry-max-backoff:
|
||||||
|
description: >
|
||||||
|
Maximum backoff time in seconds between retry attempts.
|
||||||
|
The actual backoff is randomly chosen between min and max.
|
||||||
|
default: 20
|
||||||
github-server-url:
|
github-server-url:
|
||||||
description: The base URL for the GitHub instance that you are trying to clone from, will use environment defaults to fetch from the same instance that the workflow is running from unless specified. Example URLs are https://github.com or https://my-ghes-server.example.com
|
description: The base URL for the GitHub instance that you are trying to clone from, will use environment defaults to fetch from the same instance that the workflow is running from unless specified. Example URLs are https://github.com or https://my-ghes-server.example.com
|
||||||
required: false
|
required: false
|
||||||
|
|||||||
91
dist/index.js
vendored
91
dist/index.js
vendored
@ -678,6 +678,8 @@ class GitCommandManager {
|
|||||||
this.doSparseCheckout = false;
|
this.doSparseCheckout = false;
|
||||||
this.workingDirectory = '';
|
this.workingDirectory = '';
|
||||||
this.gitVersion = new git_version_1.GitVersion();
|
this.gitVersion = new git_version_1.GitVersion();
|
||||||
|
this.timeoutMs = 0;
|
||||||
|
this.networkRetryHelper = new retryHelper.RetryHelper();
|
||||||
}
|
}
|
||||||
branchDelete(remote, branch) {
|
branchDelete(remote, branch) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
@ -851,15 +853,15 @@ class GitCommandManager {
|
|||||||
args.push(arg);
|
args.push(arg);
|
||||||
}
|
}
|
||||||
const that = this;
|
const that = this;
|
||||||
yield retryHelper.execute(() => __awaiter(this, void 0, void 0, function* () {
|
yield this.networkRetryHelper.execute(() => __awaiter(this, void 0, void 0, function* () {
|
||||||
yield that.execGit(args);
|
yield that.execGit(args, false, false, {}, that.timeoutMs);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
getDefaultBranch(repositoryUrl) {
|
getDefaultBranch(repositoryUrl) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
let output;
|
let output;
|
||||||
yield retryHelper.execute(() => __awaiter(this, void 0, void 0, function* () {
|
yield this.networkRetryHelper.execute(() => __awaiter(this, void 0, void 0, function* () {
|
||||||
output = yield this.execGit([
|
output = yield this.execGit([
|
||||||
'ls-remote',
|
'ls-remote',
|
||||||
'--quiet',
|
'--quiet',
|
||||||
@ -867,7 +869,7 @@ class GitCommandManager {
|
|||||||
'--symref',
|
'--symref',
|
||||||
repositoryUrl,
|
repositoryUrl,
|
||||||
'HEAD'
|
'HEAD'
|
||||||
]);
|
], false, false, {}, this.timeoutMs);
|
||||||
}));
|
}));
|
||||||
if (output) {
|
if (output) {
|
||||||
// Satisfy compiler, will always be set
|
// Satisfy compiler, will always be set
|
||||||
@ -912,8 +914,8 @@ class GitCommandManager {
|
|||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const args = ['lfs', 'fetch', 'origin', ref];
|
const args = ['lfs', 'fetch', 'origin', ref];
|
||||||
const that = this;
|
const that = this;
|
||||||
yield retryHelper.execute(() => __awaiter(this, void 0, void 0, function* () {
|
yield this.networkRetryHelper.execute(() => __awaiter(this, void 0, void 0, function* () {
|
||||||
yield that.execGit(args);
|
yield that.execGit(args, false, false, {}, that.timeoutMs);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1107,6 +1109,12 @@ class GitCommandManager {
|
|||||||
return this.gitVersion;
|
return this.gitVersion;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
setTimeout(timeoutSeconds) {
|
||||||
|
this.timeoutMs = timeoutSeconds * 1000;
|
||||||
|
}
|
||||||
|
setRetryConfig(maxAttempts, minBackoffSeconds, maxBackoffSeconds) {
|
||||||
|
this.networkRetryHelper = new retryHelper.RetryHelper(maxAttempts, minBackoffSeconds, maxBackoffSeconds);
|
||||||
|
}
|
||||||
static createCommandManager(workingDirectory, lfs, doSparseCheckout) {
|
static createCommandManager(workingDirectory, lfs, doSparseCheckout) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const result = new GitCommandManager();
|
const result = new GitCommandManager();
|
||||||
@ -1115,7 +1123,7 @@ class GitCommandManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
execGit(args_1) {
|
execGit(args_1) {
|
||||||
return __awaiter(this, arguments, void 0, function* (args, allowAllExitCodes = false, silent = false, customListeners = {}) {
|
return __awaiter(this, arguments, void 0, function* (args, allowAllExitCodes = false, silent = false, customListeners = {}, timeoutMs = 0) {
|
||||||
fshelper.directoryExistsSync(this.workingDirectory, true);
|
fshelper.directoryExistsSync(this.workingDirectory, true);
|
||||||
const result = new GitOutput();
|
const result = new GitOutput();
|
||||||
const env = {};
|
const env = {};
|
||||||
@ -1139,7 +1147,24 @@ class GitCommandManager {
|
|||||||
ignoreReturnCode: allowAllExitCodes,
|
ignoreReturnCode: allowAllExitCodes,
|
||||||
listeners: mergedListeners
|
listeners: mergedListeners
|
||||||
};
|
};
|
||||||
result.exitCode = yield exec.exec(`"${this.gitPath}"`, args, options);
|
const execPromise = exec.exec(`"${this.gitPath}"`, args, options);
|
||||||
|
if (timeoutMs > 0) {
|
||||||
|
let timer;
|
||||||
|
const timeoutPromise = new Promise((_, reject) => {
|
||||||
|
timer = global.setTimeout(() => {
|
||||||
|
reject(new Error(`Git operation timed out after ${timeoutMs / 1000} seconds: git ${args.slice(0, 3).join(' ')}...`));
|
||||||
|
}, timeoutMs);
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
result.exitCode = yield Promise.race([execPromise, timeoutPromise]);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
clearTimeout(timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.exitCode = yield execPromise;
|
||||||
|
}
|
||||||
result.stdout = stdout.join('');
|
result.stdout = stdout.join('');
|
||||||
core.debug(result.exitCode.toString());
|
core.debug(result.exitCode.toString());
|
||||||
core.debug(result.stdout);
|
core.debug(result.stdout);
|
||||||
@ -1448,6 +1473,10 @@ function getSource(settings) {
|
|||||||
core.startGroup('Getting Git version info');
|
core.startGroup('Getting Git version info');
|
||||||
const git = yield getGitCommandManager(settings);
|
const git = yield getGitCommandManager(settings);
|
||||||
core.endGroup();
|
core.endGroup();
|
||||||
|
if (git) {
|
||||||
|
git.setTimeout(settings.timeout);
|
||||||
|
git.setRetryConfig(settings.retryMaxAttempts, settings.retryMinBackoff, settings.retryMaxBackoff);
|
||||||
|
}
|
||||||
let authHelper = null;
|
let authHelper = null;
|
||||||
try {
|
try {
|
||||||
if (git) {
|
if (git) {
|
||||||
@ -2095,6 +2124,32 @@ function getInputs() {
|
|||||||
// Determine the GitHub URL that the repository is being hosted from
|
// Determine the GitHub URL that the repository is being hosted from
|
||||||
result.githubServerUrl = core.getInput('github-server-url');
|
result.githubServerUrl = core.getInput('github-server-url');
|
||||||
core.debug(`GitHub Host URL = ${result.githubServerUrl}`);
|
core.debug(`GitHub Host URL = ${result.githubServerUrl}`);
|
||||||
|
// Timeout (per-attempt, like k8s timeoutSeconds)
|
||||||
|
result.timeout = Math.floor(Number(core.getInput('timeout') || '300'));
|
||||||
|
if (isNaN(result.timeout) || result.timeout < 0) {
|
||||||
|
result.timeout = 300;
|
||||||
|
}
|
||||||
|
core.debug(`timeout = ${result.timeout}`);
|
||||||
|
// Retry max attempts (like k8s failureThreshold)
|
||||||
|
result.retryMaxAttempts = Math.floor(Number(core.getInput('retry-max-attempts') || '3'));
|
||||||
|
if (isNaN(result.retryMaxAttempts) || result.retryMaxAttempts < 1) {
|
||||||
|
result.retryMaxAttempts = 3;
|
||||||
|
}
|
||||||
|
core.debug(`retry max attempts = ${result.retryMaxAttempts}`);
|
||||||
|
// Retry backoff (like k8s periodSeconds, but as a min/max range)
|
||||||
|
result.retryMinBackoff = Math.floor(Number(core.getInput('retry-min-backoff') || '10'));
|
||||||
|
if (isNaN(result.retryMinBackoff) || result.retryMinBackoff < 0) {
|
||||||
|
result.retryMinBackoff = 10;
|
||||||
|
}
|
||||||
|
core.debug(`retry min backoff = ${result.retryMinBackoff}`);
|
||||||
|
result.retryMaxBackoff = Math.floor(Number(core.getInput('retry-max-backoff') || '20'));
|
||||||
|
if (isNaN(result.retryMaxBackoff) || result.retryMaxBackoff < 0) {
|
||||||
|
result.retryMaxBackoff = 20;
|
||||||
|
}
|
||||||
|
if (result.retryMaxBackoff < result.retryMinBackoff) {
|
||||||
|
result.retryMaxBackoff = result.retryMinBackoff;
|
||||||
|
}
|
||||||
|
core.debug(`retry max backoff = ${result.retryMaxBackoff}`);
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -5260,6 +5315,7 @@ class Context {
|
|||||||
this.action = process.env.GITHUB_ACTION;
|
this.action = process.env.GITHUB_ACTION;
|
||||||
this.actor = process.env.GITHUB_ACTOR;
|
this.actor = process.env.GITHUB_ACTOR;
|
||||||
this.job = process.env.GITHUB_JOB;
|
this.job = process.env.GITHUB_JOB;
|
||||||
|
this.runAttempt = parseInt(process.env.GITHUB_RUN_ATTEMPT, 10);
|
||||||
this.runNumber = parseInt(process.env.GITHUB_RUN_NUMBER, 10);
|
this.runNumber = parseInt(process.env.GITHUB_RUN_NUMBER, 10);
|
||||||
this.runId = parseInt(process.env.GITHUB_RUN_ID, 10);
|
this.runId = parseInt(process.env.GITHUB_RUN_ID, 10);
|
||||||
this.apiUrl = (_a = process.env.GITHUB_API_URL) !== null && _a !== void 0 ? _a : `https://api.github.com`;
|
this.apiUrl = (_a = process.env.GITHUB_API_URL) !== null && _a !== void 0 ? _a : `https://api.github.com`;
|
||||||
@ -6136,7 +6192,7 @@ class HttpClient {
|
|||||||
}
|
}
|
||||||
const usingSsl = parsedUrl.protocol === 'https:';
|
const usingSsl = parsedUrl.protocol === 'https:';
|
||||||
proxyAgent = new undici_1.ProxyAgent(Object.assign({ uri: proxyUrl.href, pipelining: !this._keepAlive ? 0 : 1 }, ((proxyUrl.username || proxyUrl.password) && {
|
proxyAgent = new undici_1.ProxyAgent(Object.assign({ uri: proxyUrl.href, pipelining: !this._keepAlive ? 0 : 1 }, ((proxyUrl.username || proxyUrl.password) && {
|
||||||
token: `${proxyUrl.username}:${proxyUrl.password}`
|
token: `Basic ${Buffer.from(`${proxyUrl.username}:${proxyUrl.password}`).toString('base64')}`
|
||||||
})));
|
})));
|
||||||
this._proxyAgentDispatcher = proxyAgent;
|
this._proxyAgentDispatcher = proxyAgent;
|
||||||
if (usingSsl && this._ignoreSslError) {
|
if (usingSsl && this._ignoreSslError) {
|
||||||
@ -6250,11 +6306,11 @@ function getProxyUrl(reqUrl) {
|
|||||||
})();
|
})();
|
||||||
if (proxyVar) {
|
if (proxyVar) {
|
||||||
try {
|
try {
|
||||||
return new URL(proxyVar);
|
return new DecodedURL(proxyVar);
|
||||||
}
|
}
|
||||||
catch (_a) {
|
catch (_a) {
|
||||||
if (!proxyVar.startsWith('http://') && !proxyVar.startsWith('https://'))
|
if (!proxyVar.startsWith('http://') && !proxyVar.startsWith('https://'))
|
||||||
return new URL(`http://${proxyVar}`);
|
return new DecodedURL(`http://${proxyVar}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -6313,6 +6369,19 @@ function isLoopbackAddress(host) {
|
|||||||
hostLower.startsWith('[::1]') ||
|
hostLower.startsWith('[::1]') ||
|
||||||
hostLower.startsWith('[0:0:0:0:0:0:0:1]'));
|
hostLower.startsWith('[0:0:0:0:0:0:0:1]'));
|
||||||
}
|
}
|
||||||
|
class DecodedURL extends URL {
|
||||||
|
constructor(url, base) {
|
||||||
|
super(url, base);
|
||||||
|
this._decodedUsername = decodeURIComponent(super.username);
|
||||||
|
this._decodedPassword = decodeURIComponent(super.password);
|
||||||
|
}
|
||||||
|
get username() {
|
||||||
|
return this._decodedUsername;
|
||||||
|
}
|
||||||
|
get password() {
|
||||||
|
return this._decodedPassword;
|
||||||
|
}
|
||||||
|
}
|
||||||
//# sourceMappingURL=proxy.js.map
|
//# sourceMappingURL=proxy.js.map
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|||||||
123
package-lock.json
generated
123
package-lock.json
generated
@ -69,20 +69,25 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/github": {
|
"node_modules/@actions/github": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/github/-/github-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/github/-/github-6.0.1.tgz",
|
||||||
"integrity": "sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g==",
|
"integrity": "sha512-xbZVcaqD4XnQAe35qSQqskb3SqIAfRyLBrHMd/8TuL7hJSz2QtbDwnNM8zWx4zO5l2fnGtseNE3MbEvD7BxVMw==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/http-client": "^2.2.0",
|
"@actions/http-client": "^2.2.0",
|
||||||
"@octokit/core": "^5.0.1",
|
"@octokit/core": "^5.0.1",
|
||||||
"@octokit/plugin-paginate-rest": "^9.0.0",
|
"@octokit/plugin-paginate-rest": "^9.2.2",
|
||||||
"@octokit/plugin-rest-endpoint-methods": "^10.0.0"
|
"@octokit/plugin-rest-endpoint-methods": "^10.4.0",
|
||||||
|
"@octokit/request": "^8.4.1",
|
||||||
|
"@octokit/request-error": "^5.1.1",
|
||||||
|
"undici": "^5.28.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/http-client": {
|
"node_modules/@actions/http-client": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz",
|
||||||
"integrity": "sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw==",
|
"integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tunnel": "^0.0.6",
|
"tunnel": "^0.0.6",
|
||||||
"undici": "^5.25.4"
|
"undici": "^5.25.4"
|
||||||
@ -681,10 +686,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/eslintrc/node_modules/minimatch": {
|
"node_modules/@eslint/eslintrc/node_modules/minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
},
|
},
|
||||||
@ -741,10 +747,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@humanwhocodes/config-array/node_modules/minimatch": {
|
"node_modules/@humanwhocodes/config-array/node_modules/minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
},
|
},
|
||||||
@ -810,10 +817,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
|
"node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
|
||||||
"version": "3.14.1",
|
"version": "3.14.2",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
|
||||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
"integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"argparse": "^1.0.7",
|
"argparse": "^1.0.7",
|
||||||
"esprima": "^4.0.0"
|
"esprima": "^4.0.0"
|
||||||
@ -1784,10 +1792,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ajv": {
|
"node_modules/ajv": {
|
||||||
"version": "6.12.6",
|
"version": "6.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz",
|
||||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
"integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fast-deep-equal": "^3.1.1",
|
"fast-deep-equal": "^3.1.1",
|
||||||
"fast-json-stable-stringify": "^2.0.0",
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
@ -3136,10 +3145,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-import/node_modules/minimatch": {
|
"node_modules/eslint-plugin-import/node_modules/minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
},
|
},
|
||||||
@ -3214,10 +3224,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": {
|
"node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
},
|
},
|
||||||
@ -3313,10 +3324,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint/node_modules/minimatch": {
|
"node_modules/eslint/node_modules/minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
},
|
},
|
||||||
@ -3536,10 +3548,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/filelist/node_modules/minimatch": {
|
"node_modules/filelist/node_modules/minimatch": {
|
||||||
"version": "5.1.6",
|
"version": "5.1.9",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
|
||||||
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
|
"integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^2.0.1"
|
"brace-expansion": "^2.0.1"
|
||||||
},
|
},
|
||||||
@ -3590,10 +3603,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/flatted": {
|
"node_modules/flatted": {
|
||||||
"version": "3.3.1",
|
"version": "3.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
|
||||||
"integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
|
"integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/for-each": {
|
"node_modules/for-each": {
|
||||||
"version": "0.3.3",
|
"version": "0.3.3",
|
||||||
@ -3779,10 +3793,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/glob/node_modules/minimatch": {
|
"node_modules/glob/node_modules/minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
},
|
},
|
||||||
@ -4579,10 +4594,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/jake/node_modules/minimatch": {
|
"node_modules/jake/node_modules/minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
},
|
},
|
||||||
@ -5186,10 +5202,11 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/js-yaml": {
|
"node_modules/js-yaml": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
|
||||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"argparse": "^2.0.1"
|
"argparse": "^2.0.1"
|
||||||
},
|
},
|
||||||
@ -5486,12 +5503,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "9.0.4",
|
"version": "9.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
|
||||||
"integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
|
"integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^2.0.1"
|
"brace-expansion": "^2.0.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16 || 14 >=14.17"
|
"node": ">=16 || 14 >=14.17"
|
||||||
@ -6564,10 +6582,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/test-exclude/node_modules/minimatch": {
|
"node_modules/test-exclude/node_modules/minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -80,6 +80,12 @@ export interface IGitCommandManager {
|
|||||||
): Promise<string[]>
|
): Promise<string[]>
|
||||||
tryReset(): Promise<boolean>
|
tryReset(): Promise<boolean>
|
||||||
version(): Promise<GitVersion>
|
version(): Promise<GitVersion>
|
||||||
|
setTimeout(timeoutSeconds: number): void
|
||||||
|
setRetryConfig(
|
||||||
|
maxAttempts: number,
|
||||||
|
minBackoffSeconds: number,
|
||||||
|
maxBackoffSeconds: number
|
||||||
|
): void
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createCommandManager(
|
export async function createCommandManager(
|
||||||
@ -104,6 +110,8 @@ class GitCommandManager {
|
|||||||
private doSparseCheckout = false
|
private doSparseCheckout = false
|
||||||
private workingDirectory = ''
|
private workingDirectory = ''
|
||||||
private gitVersion: GitVersion = new GitVersion()
|
private gitVersion: GitVersion = new GitVersion()
|
||||||
|
private timeoutMs = 0
|
||||||
|
private networkRetryHelper = new retryHelper.RetryHelper()
|
||||||
|
|
||||||
// Private constructor; use createCommandManager()
|
// Private constructor; use createCommandManager()
|
||||||
private constructor() {}
|
private constructor() {}
|
||||||
@ -312,22 +320,28 @@ class GitCommandManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const that = this
|
const that = this
|
||||||
await retryHelper.execute(async () => {
|
await this.networkRetryHelper.execute(async () => {
|
||||||
await that.execGit(args)
|
await that.execGit(args, false, false, {}, that.timeoutMs)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDefaultBranch(repositoryUrl: string): Promise<string> {
|
async getDefaultBranch(repositoryUrl: string): Promise<string> {
|
||||||
let output: GitOutput | undefined
|
let output: GitOutput | undefined
|
||||||
await retryHelper.execute(async () => {
|
await this.networkRetryHelper.execute(async () => {
|
||||||
output = await this.execGit([
|
output = await this.execGit(
|
||||||
'ls-remote',
|
[
|
||||||
'--quiet',
|
'ls-remote',
|
||||||
'--exit-code',
|
'--quiet',
|
||||||
'--symref',
|
'--exit-code',
|
||||||
repositoryUrl,
|
'--symref',
|
||||||
'HEAD'
|
repositoryUrl,
|
||||||
])
|
'HEAD'
|
||||||
|
],
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
{},
|
||||||
|
this.timeoutMs
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
if (output) {
|
if (output) {
|
||||||
@ -381,8 +395,8 @@ class GitCommandManager {
|
|||||||
const args = ['lfs', 'fetch', 'origin', ref]
|
const args = ['lfs', 'fetch', 'origin', ref]
|
||||||
|
|
||||||
const that = this
|
const that = this
|
||||||
await retryHelper.execute(async () => {
|
await this.networkRetryHelper.execute(async () => {
|
||||||
await that.execGit(args)
|
await that.execGit(args, false, false, {}, that.timeoutMs)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -595,6 +609,22 @@ class GitCommandManager {
|
|||||||
return this.gitVersion
|
return this.gitVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setTimeout(timeoutSeconds: number): void {
|
||||||
|
this.timeoutMs = timeoutSeconds * 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
setRetryConfig(
|
||||||
|
maxAttempts: number,
|
||||||
|
minBackoffSeconds: number,
|
||||||
|
maxBackoffSeconds: number
|
||||||
|
): void {
|
||||||
|
this.networkRetryHelper = new retryHelper.RetryHelper(
|
||||||
|
maxAttempts,
|
||||||
|
minBackoffSeconds,
|
||||||
|
maxBackoffSeconds
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
static async createCommandManager(
|
static async createCommandManager(
|
||||||
workingDirectory: string,
|
workingDirectory: string,
|
||||||
lfs: boolean,
|
lfs: boolean,
|
||||||
@ -613,7 +643,8 @@ class GitCommandManager {
|
|||||||
args: string[],
|
args: string[],
|
||||||
allowAllExitCodes = false,
|
allowAllExitCodes = false,
|
||||||
silent = false,
|
silent = false,
|
||||||
customListeners = {}
|
customListeners = {},
|
||||||
|
timeoutMs = 0
|
||||||
): Promise<GitOutput> {
|
): Promise<GitOutput> {
|
||||||
fshelper.directoryExistsSync(this.workingDirectory, true)
|
fshelper.directoryExistsSync(this.workingDirectory, true)
|
||||||
|
|
||||||
@ -644,7 +675,28 @@ class GitCommandManager {
|
|||||||
listeners: mergedListeners
|
listeners: mergedListeners
|
||||||
}
|
}
|
||||||
|
|
||||||
result.exitCode = await exec.exec(`"${this.gitPath}"`, args, options)
|
const execPromise = exec.exec(`"${this.gitPath}"`, args, options)
|
||||||
|
|
||||||
|
if (timeoutMs > 0) {
|
||||||
|
let timer: ReturnType<typeof setTimeout>
|
||||||
|
const timeoutPromise = new Promise<never>((_, reject) => {
|
||||||
|
timer = global.setTimeout(() => {
|
||||||
|
reject(
|
||||||
|
new Error(
|
||||||
|
`Git operation timed out after ${timeoutMs / 1000} seconds: git ${args.slice(0, 3).join(' ')}...`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}, timeoutMs)
|
||||||
|
})
|
||||||
|
try {
|
||||||
|
result.exitCode = await Promise.race([execPromise, timeoutPromise])
|
||||||
|
} finally {
|
||||||
|
clearTimeout(timer!)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.exitCode = await execPromise
|
||||||
|
}
|
||||||
|
|
||||||
result.stdout = stdout.join('')
|
result.stdout = stdout.join('')
|
||||||
|
|
||||||
core.debug(result.exitCode.toString())
|
core.debug(result.exitCode.toString())
|
||||||
|
|||||||
@ -39,6 +39,15 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
|
|||||||
const git = await getGitCommandManager(settings)
|
const git = await getGitCommandManager(settings)
|
||||||
core.endGroup()
|
core.endGroup()
|
||||||
|
|
||||||
|
if (git) {
|
||||||
|
git.setTimeout(settings.timeout)
|
||||||
|
git.setRetryConfig(
|
||||||
|
settings.retryMaxAttempts,
|
||||||
|
settings.retryMinBackoff,
|
||||||
|
settings.retryMaxBackoff
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
let authHelper: gitAuthHelper.IGitAuthHelper | null = null
|
let authHelper: gitAuthHelper.IGitAuthHelper | null = null
|
||||||
try {
|
try {
|
||||||
if (git) {
|
if (git) {
|
||||||
|
|||||||
@ -118,4 +118,27 @@ export interface IGitSourceSettings {
|
|||||||
* User override on the GitHub Server/Host URL that hosts the repository to be cloned
|
* User override on the GitHub Server/Host URL that hosts the repository to be cloned
|
||||||
*/
|
*/
|
||||||
githubServerUrl: string | undefined
|
githubServerUrl: string | undefined
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timeout in seconds for each network git operation attempt (fetch, lfs-fetch, ls-remote).
|
||||||
|
* 0 means no timeout. Similar to Kubernetes probe timeoutSeconds.
|
||||||
|
*/
|
||||||
|
timeout: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of retry attempts for failed network git operations.
|
||||||
|
* Similar to Kubernetes probe failureThreshold.
|
||||||
|
*/
|
||||||
|
retryMaxAttempts: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimum backoff time in seconds between retry attempts.
|
||||||
|
* Similar to Kubernetes probe periodSeconds.
|
||||||
|
*/
|
||||||
|
retryMinBackoff: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum backoff time in seconds between retry attempts.
|
||||||
|
*/
|
||||||
|
retryMaxBackoff: number
|
||||||
}
|
}
|
||||||
|
|||||||
@ -161,5 +161,41 @@ export async function getInputs(): Promise<IGitSourceSettings> {
|
|||||||
result.githubServerUrl = core.getInput('github-server-url')
|
result.githubServerUrl = core.getInput('github-server-url')
|
||||||
core.debug(`GitHub Host URL = ${result.githubServerUrl}`)
|
core.debug(`GitHub Host URL = ${result.githubServerUrl}`)
|
||||||
|
|
||||||
|
// Timeout (per-attempt, like k8s timeoutSeconds)
|
||||||
|
result.timeout = Math.floor(Number(core.getInput('timeout') || '300'))
|
||||||
|
if (isNaN(result.timeout) || result.timeout < 0) {
|
||||||
|
result.timeout = 300
|
||||||
|
}
|
||||||
|
core.debug(`timeout = ${result.timeout}`)
|
||||||
|
|
||||||
|
// Retry max attempts (like k8s failureThreshold)
|
||||||
|
result.retryMaxAttempts = Math.floor(
|
||||||
|
Number(core.getInput('retry-max-attempts') || '3')
|
||||||
|
)
|
||||||
|
if (isNaN(result.retryMaxAttempts) || result.retryMaxAttempts < 1) {
|
||||||
|
result.retryMaxAttempts = 3
|
||||||
|
}
|
||||||
|
core.debug(`retry max attempts = ${result.retryMaxAttempts}`)
|
||||||
|
|
||||||
|
// Retry backoff (like k8s periodSeconds, but as a min/max range)
|
||||||
|
result.retryMinBackoff = Math.floor(
|
||||||
|
Number(core.getInput('retry-min-backoff') || '10')
|
||||||
|
)
|
||||||
|
if (isNaN(result.retryMinBackoff) || result.retryMinBackoff < 0) {
|
||||||
|
result.retryMinBackoff = 10
|
||||||
|
}
|
||||||
|
core.debug(`retry min backoff = ${result.retryMinBackoff}`)
|
||||||
|
|
||||||
|
result.retryMaxBackoff = Math.floor(
|
||||||
|
Number(core.getInput('retry-max-backoff') || '20')
|
||||||
|
)
|
||||||
|
if (isNaN(result.retryMaxBackoff) || result.retryMaxBackoff < 0) {
|
||||||
|
result.retryMaxBackoff = 20
|
||||||
|
}
|
||||||
|
if (result.retryMaxBackoff < result.retryMinBackoff) {
|
||||||
|
result.retryMaxBackoff = result.retryMinBackoff
|
||||||
|
}
|
||||||
|
core.debug(`retry max backoff = ${result.retryMaxBackoff}`)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user