mirror of
https://github.com/peaceiris/actions-hugo.git
synced 2026-06-05 11:08:41 +02:00
b1937e141c
## Summary Rebases the Hugo package naming fix from #609 on top of the current `main` branch, including the installer flow added in #687. - Derive Hugo release asset OS and architecture naming conventions from the requested Hugo version. - Apply those conventions when selecting OS and architecture segments, including the 0.102.x macOS universal boundary, 0.103+ downcased OS names, Windows zip assets, and Linux ARM assets. - Add table-driven tests for pre-0.102, 0.102.x, and 0.103+ naming behavior, plus URL coverage for the corrected release asset names. ## Changes - Add `getConventions` to centralize version-based release asset naming decisions. - Update `getOS` and `getArch` to use convention flags for macOS, lower-case OS names, standardized architecture names, and the Windows ARM support boundary. - Update `getURL` to generate candidate URLs for downcased Windows and Linux assets, and for darwin universal archives. - Wire convention detection into `installer` before generating candidate Hugo release asset URLs. - Expand unit coverage for OS, architecture, convention, and URL behavior. ## Checklist - [x] I have read the latest README and followed the instructions. - [x] I have added or updated tests for behavior changes. - [x] README.md and action.yml updates are not needed because inputs and action metadata are unchanged. - [x] I have run the relevant verification commands. ## References - Rebased follow-up for https://github.com/peaceiris/actions-hugo/pull/609 - References https://github.com/peaceiris/actions-hugo/issues/605 and https://github.com/peaceiris/actions-hugo/issues/608 - Based on `main` after https://github.com/peaceiris/actions-hugo/pull/687 ## Verification - [x] `RUNNER_TEMP=/private/tmp npm run all` - [ ] `npm run build` was not run because this branch does not update bundled output and current `main` removed `lib/index.js`. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Version-aware conventions control OS and architecture naming, including macOS universal asset support and expanded darwin/macOS patterns. * **Refactor** * Conventions centralized and applied across installer and URL generation; OS/arch inputs accept varied casing and naming variants. * **Tests** * Expanded, data-driven parameterized tests for conventions, OS/arch mappings, URL variants, and error cases. * Replaced network stubs with deterministic fetch-mock helpers for test isolation. [](https://app.coderabbit.ai/change-stack/peaceiris/actions-hugo/pull/688) <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Michael T Lombardi <michael.t.lombardi@gmail.com> Co-authored-by: codefactor-io <support@codefactor.io> Co-authored-by: Codex <noreply@openai.com>
134 lines
3.9 KiB
TypeScript
134 lines
3.9 KiB
TypeScript
import * as core from '@actions/core';
|
|
import * as tc from '@actions/tool-cache';
|
|
import * as io from '@actions/io';
|
|
import * as exec from '@actions/exec';
|
|
import {getConventions} from './get-conventions';
|
|
import getOS from './get-os';
|
|
import getArch from './get-arch';
|
|
import getURL from './get-url';
|
|
import * as path from 'path';
|
|
import {Tool, Action} from './constants';
|
|
|
|
export interface DownloadedAsset {
|
|
path: string;
|
|
url: string;
|
|
}
|
|
|
|
export function getHomeDir(): string {
|
|
let homedir = '';
|
|
|
|
if (process.platform === 'win32') {
|
|
homedir = process.env['USERPROFILE'] || 'C:\\';
|
|
} else {
|
|
homedir = `${process.env.HOME}`;
|
|
}
|
|
|
|
core.debug(`homeDir: ${homedir}`);
|
|
|
|
return homedir;
|
|
}
|
|
|
|
export async function createWorkDir(): Promise<string> {
|
|
const workDir = path.join(getHomeDir(), Action.WorkDirName);
|
|
await io.mkdirP(workDir);
|
|
core.debug(`workDir: ${workDir}`);
|
|
return workDir;
|
|
}
|
|
|
|
export async function createTempDir(workDir: string): Promise<string> {
|
|
const tempDir = path.join(workDir, Action.TempDirName);
|
|
await io.mkdirP(tempDir);
|
|
core.debug(`tempDir: ${tempDir}`);
|
|
return tempDir;
|
|
}
|
|
|
|
export async function createBinDir(workDir: string): Promise<string> {
|
|
const binDir = path.join(workDir, 'bin');
|
|
await io.mkdirP(binDir);
|
|
core.addPath(binDir);
|
|
core.debug(`binDir: ${binDir}`);
|
|
return binDir;
|
|
}
|
|
|
|
export function isRetryableDownloadError(error: unknown): boolean {
|
|
const message = error instanceof Error ? error.message : `${error}`;
|
|
return (
|
|
message.includes('Unexpected HTTP response: 404') ||
|
|
message.includes('Code(404)') ||
|
|
(message.includes('404') && message.includes('Not Found'))
|
|
);
|
|
}
|
|
|
|
export function isWindowsAsset(assetURL: string): boolean {
|
|
return /(?:Windows[-_]|windows[-_])/.test(assetURL);
|
|
}
|
|
|
|
export async function downloadHugoAsset(toolURLs: string[]): Promise<DownloadedAsset> {
|
|
for (const toolURL of toolURLs) {
|
|
core.debug(`toolURL: ${toolURL}`);
|
|
|
|
try {
|
|
return {
|
|
path: await tc.downloadTool(toolURL),
|
|
url: toolURL
|
|
};
|
|
} catch (error) {
|
|
if (!isRetryableDownloadError(error)) {
|
|
throw error;
|
|
}
|
|
|
|
core.debug(`Hugo asset not found at ${toolURL}`);
|
|
}
|
|
}
|
|
|
|
throw new Error(
|
|
`Unable to find a compatible Hugo release asset for this runner. Tried:\n${toolURLs.join('\n')}`
|
|
);
|
|
}
|
|
|
|
export async function extractHugoAsset(
|
|
assetPath: string,
|
|
assetURL: string,
|
|
tempDir: string,
|
|
binDir: string
|
|
): Promise<void> {
|
|
let toolBin = '';
|
|
|
|
if (assetURL.endsWith('.zip')) {
|
|
const toolExtractedFolder: string = await tc.extractZip(assetPath, tempDir);
|
|
const toolCmd = isWindowsAsset(assetURL) ? `${Tool.CmdName}.exe` : Tool.CmdName;
|
|
toolBin = path.join(toolExtractedFolder, toolCmd);
|
|
} else if (assetURL.endsWith('.pkg')) {
|
|
const pkgExtractedFolder = path.join(tempDir, 'pkg');
|
|
await exec.exec('pkgutil', ['--expand-full', assetPath, pkgExtractedFolder]);
|
|
toolBin = path.join(pkgExtractedFolder, 'Payload', Tool.CmdName);
|
|
} else {
|
|
const toolExtractedFolder: string = await tc.extractTar(assetPath, tempDir);
|
|
toolBin = path.join(toolExtractedFolder, Tool.CmdName);
|
|
}
|
|
|
|
await io.mv(toolBin, binDir);
|
|
}
|
|
|
|
export async function installer(version: string): Promise<void> {
|
|
const extended: string = core.getInput('extended');
|
|
core.debug(`Hugo extended: ${extended}`);
|
|
|
|
const conventions = getConventions(version);
|
|
|
|
const osName: string = getOS(process.platform, conventions);
|
|
core.debug(`Operating System: ${osName}`);
|
|
|
|
const archName: string = getArch(process.arch, osName, conventions);
|
|
core.debug(`Processor Architecture: ${archName}`);
|
|
|
|
const toolURLs: string[] = getURL(osName, archName, extended, version);
|
|
|
|
const workDir = await createWorkDir();
|
|
const binDir = await createBinDir(workDir);
|
|
const tempDir = await createTempDir(workDir);
|
|
|
|
const toolAsset: DownloadedAsset = await downloadHugoAsset(toolURLs);
|
|
await extractHugoAsset(toolAsset.path, toolAsset.url, tempDir, binDir);
|
|
}
|