Skip to content

Commit 8bf3174

Browse files
committed
fix: Windows MSI download on self-hosted runners
On self-hosted runners, the tool cache directory persists between runs. When GitHub's cloud cache doesn't have an entry (first run, evicted, etc.), but the local MSI file exists from a previous run, tc.downloadTool() fails with "Destination file path already exists". This fix checks if the existing MSI has a valid checksum before downloading: - If valid: reuse it (skip download) - If invalid: delete and re-download Signed-off-by: Dorin Geman <[email protected]>
1 parent 53acf82 commit 8bf3174

File tree

1 file changed

+29
-14
lines changed

1 file changed

+29
-14
lines changed

src/main.ts

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -509,23 +509,38 @@ async function installTailscaleWindows(
509509

510510
// Download MSI
511511
const downloadUrl = `${baseUrl}/tailscale-setup-${config.resolvedVersion}-${config.arch}.msi`;
512-
core.info(`Downloading ${downloadUrl}`);
513-
514-
const downloadedMsiPath = await tc.downloadTool(downloadUrl, msiPath);
515-
516-
// Verify checksum
517-
const actualSha = await calculateFileSha256(downloadedMsiPath);
518512
const expectedSha = config.sha256Sum.trim().toLowerCase();
519-
core.info(`Expected sha256: ${expectedSha}`);
520-
core.info(`Actual sha256: ${actualSha}`);
521-
if (actualSha !== expectedSha) {
522-
throw new Error("SHA256 checksum mismatch");
513+
514+
// Check if MSI already exists with correct checksum (for self-hosted runners)
515+
let needsDownload = true;
516+
if (fs.existsSync(msiPath)) {
517+
const existingSha = await calculateFileSha256(msiPath);
518+
if (existingSha === expectedSha) {
519+
core.info(`Using existing MSI at ${msiPath} (checksum verified)`);
520+
needsDownload = false;
521+
} else {
522+
core.info(`Existing MSI checksum mismatch, re-downloading`);
523+
fs.unlinkSync(msiPath);
524+
}
523525
}
524526

525-
// Keep the MSI file in toolPath for caching (don't delete it)
526-
// The downloadedMsiPath is in temp, but we want to keep it in toolPath
527-
if (downloadedMsiPath !== msiPath) {
528-
fs.copyFileSync(downloadedMsiPath, msiPath);
527+
if (needsDownload) {
528+
core.info(`Downloading ${downloadUrl}`);
529+
const downloadedMsiPath = await tc.downloadTool(downloadUrl, msiPath);
530+
531+
// Verify checksum
532+
const actualSha = await calculateFileSha256(downloadedMsiPath);
533+
core.info(`Expected sha256: ${expectedSha}`);
534+
core.info(`Actual sha256: ${actualSha}`);
535+
if (actualSha !== expectedSha) {
536+
throw new Error("SHA256 checksum mismatch");
537+
}
538+
539+
// Keep the MSI file in toolPath for caching (don't delete it)
540+
// The downloadedMsiPath is in temp, but we want to keep it in toolPath
541+
if (downloadedMsiPath !== msiPath) {
542+
fs.copyFileSync(downloadedMsiPath, msiPath);
543+
}
529544
}
530545
}
531546

0 commit comments

Comments
 (0)