Merge pull request #264 from aminya/powershell-ubuntu-24 [skip ci]

This commit is contained in:
Amin Yahyaabadi 2024-08-21 15:45:47 -07:00 committed by GitHub
commit e486e3676a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 322 additions and 151 deletions

View File

@ -84,7 +84,7 @@ jobs:
- windows-2022
- ubuntu-24.04
- macos-13
- macos-12
# - macos-12
node:
- 22
pnpm:

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,6 @@
import { addExeExt } from "patha"
import semverCoerce from "semver/functions/coerce"
import semverLte from "semver/functions/lte"
import { extractTarByExe, extractZip } from "../utils/setup/extract.js"
import { type InstallationInfo, type PackageInfo, setupBin } from "../utils/setup/setupBin.js"
/** Get the platform data for cmake */
@ -21,7 +20,6 @@ function getCmakePackageInfo(version: string, platform: NodeJS.Platform, arch: s
binRelativeDir: "bin/",
binFileName: addExeExt("cmake"),
extractedFolderName: folderName,
extractFunction: extractZip,
url: `https://github.com/Kitware/CMake/releases/download/v${version}/${folderName}.zip`,
}
}
@ -33,7 +31,6 @@ function getCmakePackageInfo(version: string, platform: NodeJS.Platform, arch: s
binRelativeDir: "CMake.app/Contents/bin/",
binFileName: addExeExt("cmake"),
extractedFolderName: folderName,
extractFunction: extractTarByExe,
url: `https://github.com/Kitware/CMake/releases/download/v${version}/${folderName}.tar.gz`,
}
}
@ -50,7 +47,6 @@ function getCmakePackageInfo(version: string, platform: NodeJS.Platform, arch: s
binRelativeDir: "bin/",
binFileName: addExeExt("cmake"),
extractedFolderName: folderName,
extractFunction: extractTarByExe,
url: `https://github.com/Kitware/CMake/releases/download/v${version}/${folderName}.tar.gz`,
}
}

View File

@ -3,7 +3,6 @@ import { addPath } from "envosman"
import { addExeExt, join } from "patha"
import { installAptPack } from "setup-apt"
import { setupGraphviz } from "../graphviz/graphviz.js"
import { extractTar, extractZip } from "../utils/setup/extract.js"
import { type InstallationInfo, type PackageInfo, setupBin } from "../utils/setup/setupBin.js"
import { setupBrewPack } from "../utils/setup/setupBrewPack.js"
import { setupChocoPack } from "../utils/setup/setupChocoPack.js"
@ -31,7 +30,6 @@ function getDoxygenPackageInfo(version: string, platform: NodeJS.Platform, _arch
binRelativeDir: "bin/",
binFileName: addExeExt("doxygen"),
extractedFolderName: folderName,
extractFunction: extractTar,
url: `https://www.doxygen.nl/files/${folderName}.linux.bin.tar.gz`,
}
}
@ -41,7 +39,6 @@ function getDoxygenPackageInfo(version: string, platform: NodeJS.Platform, _arch
binRelativeDir: "",
binFileName: addExeExt("doxygen"),
extractedFolderName: folderName,
extractFunction: extractZip,
url: `https://www.doxygen.nl/files/${folderName}.windows.x64.bin.zip`,
}
}

View File

@ -23,7 +23,6 @@ function getDownloadKcovPackageInfo(version: string): PackageInfo {
extractedFolderName: "",
binRelativeDir: "usr/local/bin",
binFileName: addExeExt("kcov"),
extractFunction: extractTarByExe,
}
}

View File

@ -1,5 +1,4 @@
import { addExeExt } from "patha"
import { extractZip } from "../utils/setup/extract.js"
import { type InstallationInfo, type PackageInfo, setupBin } from "../utils/setup/setupBin.js"
/** Get the platform name Ninja uses in their download links */
@ -24,7 +23,6 @@ function getNinjaPackageInfo(version: string, platform: NodeJS.Platform, _arch:
binRelativeDir: "",
binFileName: addExeExt("ninja"),
extractedFolderName: "",
extractFunction: extractZip,
url: `https://github.com/ninja-build/ninja/releases/download/v${version}/ninja-${ninjaPlatform}.zip`,
}
}

View File

@ -1,18 +1,28 @@
import { GITHUB_ACTIONS } from "ci-info"
import { testBin } from "../../utils/tests/test-helpers.js"
import { cleanupTmpDir, setupTmpDir, testBin } from "../../utils/tests/test-helpers.js"
import { getVersion } from "../../versions/versions.js"
import { setupPowershell } from "../powershell.js"
jest.setTimeout(300000)
describe("setup-powershell", () => {
let directory: string
beforeEach(async () => {
directory = await setupTmpDir("powershell")
process.env.CACHE_TOOLS = "true"
})
it("should setup powershell", async () => {
if (process.platform === "win32" && GITHUB_ACTIONS) {
// results in errors
return
}
const installInfo = await setupPowershell(getVersion("powershell", undefined), "", process.arch)
const installInfo = await setupPowershell(getVersion("powershell", undefined), directory, process.arch)
await testBin("pwsh", ["--version"], installInfo.binDir)
})
afterEach(async () => {
await cleanupTmpDir("ninja")
}, 100000)
})

View File

@ -1,18 +1,76 @@
import { execRootSync } from "admina"
import { error } from "ci-log"
import { addPath } from "envosman"
import { addExeExt } from "patha"
import { installAptPack } from "setup-apt"
import { rcOptions } from "../cli-options.js"
import { hasDnf } from "../utils/env/hasDnf.js"
import { isArch } from "../utils/env/isArch.js"
import { isUbuntu } from "../utils/env/isUbuntu.js"
import { ubuntuVersion } from "../utils/env/ubuntu_version.js"
import { type PackageInfo, setupBin } from "../utils/setup/setupBin.js"
import { setupBrewPack } from "../utils/setup/setupBrewPack.js"
import { setupChocoPack } from "../utils/setup/setupChocoPack.js"
import { setupDnfPack } from "../utils/setup/setupDnfPack.js"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack.js"
/** Get the platform data for cmake */
function getPowerShellPackageInfo(version: string, platform: NodeJS.Platform, arch: string): PackageInfo {
return {
url: getPowershellUrl(platform, arch, version),
binRelativeDir: "",
binFileName: addExeExt("pwsh"),
extractedFolderName: "",
}
}
function getPowershellUrl(
platform: string,
arch: string,
version: string,
) {
switch (platform) {
case "win32": {
const osArchStr = (["ia32", "x86", "i386", "x32"].includes(arch))
? "win-x86"
: "win-x64"
return `https://github.com/PowerShell/PowerShell/releases/download/v${version}/PowerShell-${version}-${osArchStr}.zip`
}
case "darwin": {
const osArchStr = ["arm", "arm64"].includes(arch) ? "osx-arm64" : "osx-x64"
return `https://github.com/PowerShell/PowerShell/releases/download/v${version}/powershell-${version}-${osArchStr}.tar.gz`
}
case "linux": {
const archMap = {
arm64: "linux-arm64",
arm: "linux-arm64",
arm32: "linux-arm32",
aarch64: "linux-arm64",
x64: "linux-x64",
} as Record<string, string | undefined>
const osArchStr = archMap[arch] ?? "linux-x64"
// TODO support musl
return `https://github.com/PowerShell/PowerShell/releases/download/v${version}/powershell-${version}-${osArchStr}.tar.gz`
}
default:
throw new Error(`Unsupported platform '${platform}'`)
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export async function setupPowershell(version: string | undefined, _setupDir: string, _arch: string) {
export async function setupPowershell(version: string, setupDir: string, arch: string) {
try {
return await setupBin("pwsh", version, getPowerShellPackageInfo, setupDir, arch)
} catch (err) {
error(`Failed to setup pwsh via download: ${err}. Trying package managers...`)
return setupPowershellSystem(version, setupDir, arch)
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export async function setupPowershellSystem(version: string | undefined, _setupDir: string, _arch: string) {
switch (process.platform) {
case "win32": {
await setupChocoPack("powershell-core", version)

View File

@ -1,5 +1,4 @@
import { addExeExt } from "patha"
import { extractTarByExe, extractZip } from "../utils/setup/extract.js"
import { type InstallationInfo, type PackageInfo, setupBin } from "../utils/setup/setupBin.js"
/** Get the platform name task uses in their download links */
@ -31,13 +30,11 @@ function getTaskArch(arch: string) {
function getTaskPackageInfo(version: string, platform: NodeJS.Platform, arch: string): PackageInfo {
const taskPlatform = getTaskPlatform(platform)
const taskArch = getTaskArch(arch)
const isZip = platform === "win32"
const extension = isZip ? "zip" : "tar.gz"
const extension = platform === "win32" ? "zip" : "tar.gz"
return {
binRelativeDir: "",
binFileName: addExeExt("task"),
extractedFolderName: "",
extractFunction: isZip ? extractZip : extractTarByExe,
url: `https://github.com/go-task/task/releases/download/v${version}/task_${taskPlatform}_${taskArch}.${extension}`,
}
}

View File

@ -1,11 +1,67 @@
import { mkdirP } from "@actions/io"
import { grantUserWriteAccess } from "admina"
import { warning } from "ci-log"
import { info, warning } from "ci-log"
import { execa } from "execa"
import { installAptPack } from "setup-apt"
import which from "which"
import { setupSevenZip } from "../../sevenzip/sevenzip.js"
import { hasDnf } from "../env/hasDnf.js"
import { isArch } from "../env/isArch.js"
import { isUbuntu } from "../env/isUbuntu.js"
import { setupDnfPack } from "./setupDnfPack.js"
import { setupPacmanPack } from "./setupPacmanPack.js"
export { extractTar, extractXar } from "@actions/tool-cache"
export enum ArchiveType {
Tar = 0,
TarGz = 1,
TarXz = 2,
Zip = 3,
SevenZip = 4,
}
export function getArchiveType(file: string): ArchiveType {
const ext = file.split(".").pop()
if (ext === "tar") {
return ArchiveType.Tar
}
if (ext === "gz" || ext === "tgz") {
return ArchiveType.TarGz
}
if (ext === "xz" || ext === "txz") {
return ArchiveType.TarXz
}
if (ext === "zip") {
return ArchiveType.Zip
}
if (ext === "7z" || ext === "exe") {
return ArchiveType.SevenZip
}
// default to 7z
warning(`Unknown archive type: ${ext}. Defaulting to 7z`)
return ArchiveType.SevenZip
}
export function getExtractFunction(archiveType: ArchiveType) {
switch (archiveType) {
case ArchiveType.Tar:
case ArchiveType.TarGz:
return extractTarByExe
case ArchiveType.TarXz:
return extractTarByExe
case ArchiveType.Zip:
return extractZip
default:
return extract7Zip
}
}
let sevenZip: string | undefined
/// Extract 7z using 7z
@ -32,12 +88,21 @@ export function extractExe(file: string, dest: string) {
return extract7Zip(file, dest)
}
/// Extract Zip using 7z
export function extractZip(file: string, dest: string) {
/// Extract Zip using unzip or 7z
export async function extractZip(file: string, dest: string) {
// if unzip is available use it
if (which.sync("unzip", { nothrow: true }) !== null) {
await execa("unzip", [file, "-d", dest], { stdio: "inherit" })
await grantUserWriteAccess(dest)
return dest
}
return extract7Zip(file, dest)
}
export async function extractTarByExe(file: string, dest: string, stripComponents: number = 0, flags: string[] = []) {
await installTarDependencies(getArchiveType(file))
try {
await mkdirP(dest)
} catch {
@ -60,3 +125,38 @@ export async function extractTarByExe(file: string, dest: string, stripComponent
await grantUserWriteAccess(dest)
return dest
}
async function installTarDependencies(archiveType: ArchiveType) {
info("Installing tar extraction dependencies")
switch (archiveType) {
case ArchiveType.TarGz: {
if (process.platform === "linux") {
if (isArch()) {
await setupPacmanPack("gzip")
await setupPacmanPack("tar")
} else if (hasDnf()) {
await setupDnfPack([{ name: "gzip" }, { name: "tar" }])
} else if (isUbuntu()) {
await installAptPack([{ name: "gzip" }, { name: "tar" }])
}
}
break
}
case ArchiveType.TarXz: {
if (process.platform === "linux") {
if (isArch()) {
await setupPacmanPack("xz")
await setupPacmanPack("tar")
} else if (hasDnf()) {
await setupDnfPack([{ name: "xz" }, { name: "tar" }])
} else if (isUbuntu()) {
await installAptPack([{ name: "xz-utils" }, { name: "tar" }])
}
}
break
}
default:
throw new Error(`Unsupported archive type: ${archiveType} for tar extraction`)
}
}

View File

@ -1,19 +1,15 @@
import { cacheDir, downloadTool, find } from "@actions/tool-cache"
import { info } from "ci-log"
import { addPath } from "envosman"
import { join } from "patha"
import { tmpdir } from "os"
import { basename } from "path"
import { cacheDir, downloadTool, find } from "@actions/tool-cache"
import { GITHUB_ACTIONS } from "ci-info"
import { info, warning } from "ci-log"
import { addPath } from "envosman"
import { chmod } from "fs/promises"
import { pathExists } from "path-exists"
import { join } from "patha"
import retry from "retry-as-promised"
import { installAptPack } from "setup-apt"
import { maybeGetInput, rcOptions } from "../../cli-options.js"
import { hasDnf } from "../env/hasDnf.js"
import { isArch } from "../env/isArch.js"
import { isUbuntu } from "../env/isUbuntu.js"
import { setupDnfPack } from "./setupDnfPack.js"
import { setupPacmanPack } from "./setupPacmanPack.js"
import { getArchiveType, getExtractFunction } from "./extract.js"
/** A type that describes a package */
export type PackageInfo = {
@ -36,8 +32,6 @@ export type InstallationInfo = {
bin?: string
}
let didInit: boolean = false
/**
* A function that:
*
@ -88,39 +82,32 @@ export async function setupBin(
const binDir = join(installDir, binRelativeDir)
const binFile = join(binDir, binFileName)
await downloadExtractInstall(binDir, binFile, name, version, url, setupDir, extractFunction, arch)
await cacheInstallation(setupDir, name, version)
return { installDir, binDir }
}
async function downloadExtractInstall(
binDir: string,
binFile: string,
name: string,
version: string,
url: string,
setupDir: string,
givenExtractFunction: PackageInfo["extractFunction"],
arch: string,
) {
// download ane extract the package into the installation directory.
if ((await Promise.all([pathExists(binDir), pathExists(binFile)])).includes(false)) {
try {
info(`Download ${name} ${version}`)
// try to download the package 4 times with 2 seconds delay
const downloaded = await retry(
() => {
return downloadTool(url)
},
{ name: url, max: 4, backoffBase: 2000, report: (err) => info(err) },
)
if (!didInit) {
info("Installing extraction dependencies")
if (process.platform === "linux") {
if (isArch()) {
await Promise.all([setupPacmanPack("unzip"), setupPacmanPack("tar"), setupPacmanPack("xz")])
} else if (hasDnf()) {
await setupDnfPack([{ name: "unzip" }, { name: "tar" }, { name: "xz" }])
} else if (isUbuntu()) {
await installAptPack([{ name: "unzip" }, { name: "tar" }, { name: "xz-utils" }])
}
}
// eslint-disable-next-line require-atomic-updates
didInit = true
}
const downloaded = await tryDownload(name, version, url)
info(`Extracting ${downloaded} to ${setupDir}`)
await extractFunction?.(downloaded, setupDir)
// if (typeof extractedBinDir === "string") {
// binDir = extractedBinDir
// installDir = extractedBinDir
// }
const extractFunction = givenExtractFunction ?? getExtractFunction(getArchiveType(url))
await extractFunction(downloaded, setupDir)
} catch (err) {
throw new Error(`Failed to download ${name} ${version} ${arch} from ${url}: ${err}`)
}
@ -131,12 +118,40 @@ export async function setupBin(
info(`Add ${binDir} to PATH`)
await addPath(binDir, rcOptions)
// Check if the binary exists after extraction
if (!(await pathExists(binFile))) {
throw new Error(`Failed to find the binary ${binFile} after extracting ${name} ${version} ${arch}`)
}
// make the binary executable on non-windows platforms
if (process.platform !== "win32") {
try {
await chmod(binFile, "755")
} catch (err) {
warning(`Failed to make ${binFile} executable: ${err}`)
}
}
}
async function tryDownload(name: string, version: string, url: string) {
info(`Download ${name} ${version}`)
// try to download the package 4 times with 2 seconds delay
const downloaded = await retry(
() => {
const downloadedFilePath = join(process.env.RUNNER_TEMP ?? tmpdir(), `${Date.now()}-${basename(url)}`)
return downloadTool(url, downloadedFilePath)
},
{ name: url, max: 4, backoffBase: 2000, report: (err) => info(err) },
)
return downloaded
}
async function cacheInstallation(setupDir: string, name: string, version: string) {
// check if inside Github Actions. If so, cache the installation
if (GITHUB_ACTIONS && typeof process.env.RUNNER_TOOL_CACHE === "string") {
if (maybeGetInput("cache-tools") === "true" || process.env.CACHE_TOOLS === "true") {
await cacheDir(setupDir, name, version)
}
}
return { installDir, binDir }
}

View File

@ -32,6 +32,7 @@ export const DefaultVersions: Record<string, string | undefined> = {
doxygen: isArch() ? "1.11.0-4" : "1.11.0", // https://www.doxygen.nl/download.html // https://packages.ubuntu.com/search?suite=all&arch=any&searchon=names&keywords=doxygen // https://formulae.brew.sh/formula/doxygen // https://archlinux.org/packages/extra/x86_64/doxygen/
gcc: isArch() ? "13.2.1-3" : "13", // https://github.com/brechtsanders/winlibs_mingw/releases and // https://packages.ubuntu.com/search?suite=all&arch=any&searchon=names&keywords=gcc
// mingw: isArch() ? "12.2.0-1" : "8", // https://packages.ubuntu.com/search?suite=all&arch=any&searchon=names&keywords=mingw-w64 // https://archlinux.org/packages/extra/x86_64/mingw-w64-gcc/
powershell: "7.4.5", // https://github.com/PowerShell/PowerShell/releases/tag/v7.4.5
}
export const MinVersions: Record<string, string | undefined> = {