21 Commits
Author SHA1 Message Date
slawek 9138f03d35 Refactor: Simplify binary pattern handling in findBinary and findInstalledBinary functions
Test Action / test (push) Successful in 12s
2026-04-07 09:43:53 +02:00
slawek e8a9b0906d Refactor: Move installSystemPackage function to a separate module for better organization 2026-04-07 09:28:10 +02:00
slawek 544be86f08 Fix: Update actions/checkout version to v6 in workflow files
Test Action / test (push) Successful in 12s
2026-04-07 08:10:34 +02:00
slawek 97d2597552 Sync Github workflow with changes to the Gitea workflow. 2026-04-07 07:59:33 +02:00
slawek 4c45d89c83 Fix: Ensure file-type is specified for RClone setup in test workflow
Test Action / test (push) Successful in 12s
2026-04-07 07:30:22 +02:00
slawek d70ee1e8b8 Fix: Update file-name pattern for Hugo setup to include system and architecture placeholders
Test Action / test (push) Failing after 9s
2026-04-07 07:29:11 +02:00
slawek bffd6ee278 Fix: Pin dependencies and devDependencies to specific versions for stability
Test Action / test (push) Failing after 7s
2026-04-07 07:20:13 +02:00
slawek 0643b8ca01 Updated dependencies in package.json to use latest versions and Node 24.
Test Action / test (push) Failing after 7s
2026-04-07 07:15:46 +02:00
slawek 26ef54930a Fix: Correct file-type input for asset selection and enhance regex filtering debugging with dry run support
Test Action / test (push) Failing after 7s
2026-04-07 07:02:42 +02:00
slawek e7e7ee53f6 Fix: Enhance asset filtering with dry run support and update platform architecture patterns 2026-04-07 06:55:24 +02:00
slawek d2f1cb9c1a Fix: Ensure cache is always updated for test run.
Test Action / test (push) Failing after 7s
2026-04-06 23:38:07 +02:00
slawek 1a01c8fa5f Updated Action transpiled code.
Test Action / test (push) Successful in 6s
2026-04-06 23:35:42 +02:00
slawek cbfadf3488 Fix: Enhance binary pattern matching with system and architecture replacements
Test Action / test (push) Successful in 14s
2026-04-06 23:33:46 +02:00
slawek 01d844f6d9 Feat: Integrate commander for improved CLI argument parsing 2026-04-06 23:21:03 +02:00
slawek e50ae03336 Fix: Add chmod command to make CLI and check-token scripts executable 2026-04-06 22:55:40 +02:00
slawek 1896949b27 Removed cli.js from the repository - it is not needed there. 2026-04-06 22:53:21 +02:00
slawek d9d7f67247 Refactored asset matching code. 2026-04-06 22:50:25 +02:00
slawek 0132ee6665 Refactor: Simplify getMatchingAsset function parameters in CLI and matcher modules 2026-04-06 18:46:31 +02:00
slawek 89ea0cecb0 Refactor: Consolidate asset matching logic into a single function 2026-04-06 12:30:28 +02:00
slawek 3a75adedc6 Refactor: Extract filename matching logic into a separate function 2026-04-06 12:18:19 +02:00
slawek dfa641afd4 Matched functionality of the CLI with the Bash predecessor. 2026-04-06 12:00:09 +02:00
20 changed files with 44898 additions and 546 deletions
+7 -2
View File
@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: Check Authentication - name: Check Authentication
uses: ./check-token uses: ./check-token
@@ -28,19 +28,24 @@ jobs:
with: with:
repository: 'go-acme/lego' repository: 'go-acme/lego'
token: ${{ secrets.GH_TOKEN }} token: ${{ secrets.GH_TOKEN }}
update-cache: 'always'
- name: Setup Hugo - name: Setup Hugo
uses: ./ uses: ./
with: with:
repository: 'gohugoio/hugo' repository: 'gohugoio/hugo'
file-name: '~hugo_extended_[^a-z]' file-name: '~hugo_extended_[^a-z].*{{SYSTEM}}-{{ARCH}}'
file-type: 'archive'
token: ${{ secrets.GH_TOKEN }} token: ${{ secrets.GH_TOKEN }}
update-cache: 'always'
- name: Setup RClone - name: Setup RClone
uses: ./ uses: ./
with: with:
repository: 'rclone/rclone' repository: 'rclone/rclone'
file-type: 'archive'
token: ${{ secrets.GH_TOKEN }} token: ${{ secrets.GH_TOKEN }}
update-cache: 'always'
- name: Verify Installation - name: Verify Installation
run: | run: |
+4 -2
View File
@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v6
# Let's test the token first. # Let's test the token first.
- name: Check Authentication - name: Check Authentication
@@ -31,12 +31,14 @@ jobs:
uses: skoszewski/setup-github-release@v1 uses: skoszewski/setup-github-release@v1
with: with:
repository: 'gohugoio/hugo' repository: 'gohugoio/hugo'
file-name: '~hugo_extended_[^a-z]' file-name: '~hugo_extended_[^a-z].*{{SYSTEM}}-{{ARCH}}'
file-type: 'archive'
- name: Setup RClone - name: Setup RClone
uses: skoszewski/setup-github-release@v1 uses: skoszewski/setup-github-release@v1
with: with:
repository: 'rclone/rclone' repository: 'rclone/rclone'
file-type: 'archive'
- name: Verify Installation - name: Verify Installation
run: | run: |
+1
View File
@@ -4,3 +4,4 @@ lib/
*.map *.map
.DS_Store .DS_Store
.github/*.md .github/*.md
dist/cli.js
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Slawomir Koszewski
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+27 -9
View File
@@ -115,11 +115,12 @@ The following inputs are available for the GitHub Action, and as options for the
- `repository` (required): The GitHub repository in the format `owner/repo` from which to download the release. - `repository` (required): The GitHub repository in the format `owner/repo` from which to download the release.
- `file-name` (optional): The name or the regex pattern (prefixed with `~`) of the asset file to download from the release. - `file-name` (optional): The name or the regex pattern (prefixed with `~`) of the asset file to download from the release.
- `binary-name` (optional): The name or regex pattern (prefixed with `~`) of the binary to search for within the downloaded asset. Defaults to the repository name. - `binary-name` (optional): The name or regex pattern (prefixed with `~`) of the binary to search for within the downloaded asset. Defaults to the repository name.
- `file-type` (optional, default: 'archive'): The regex pattern to identify the type of the file to be downloaded. There are two predefined keywords: - `file-type` (optional): Asset type selector.
- 'archive': matches common archive file extensions like .zip, .tar.gz, .tar, .tgz, .7z. - known values: `archive`, `package`, `linux`, `macos`, `targz`.
- 'package': matches common package file extensions like .deb, .rpm, .pkg. - custom values:
- or a custom regex pattern can be provided to match specific file types. `~<regex>` for regular expression matching (anchored to the end of file name), or
extension form such as `zip` or `.tar.gz`.
- `install-path` (optional, CLI only): Custom installation directory for the CLI tool. - `install-path` (optional, CLI only): Custom installation directory for the CLI tool.
- `update-cache` (optional, default: 'false', Action only): When set to 'false', the action will use the cached version of the tool if it is already available. If set to 'true', the action will check the latest release and update the cache if a newer version is found. If set to 'always', it will always download and install, updating the cache regardless. - `update-cache` (optional, default: 'false', Action only): When set to 'false', the action will use the cached version of the tool if it is already available. If set to 'true', the action will check the latest release and update the cache if a newer version is found. If set to 'always', it will always download and install, updating the cache regardless.
@@ -139,10 +140,20 @@ Arguments:
repository The GitHub repository (owner/repo) repository The GitHub repository (owner/repo)
Options: Options:
--dry-run [level] Run in test mode (default level: 1)
Or set TEST_MODE environment variable to a value > 0
-l, --list [repository] List available assets from latest release and exit
-a, --app-name <name> Application name (optional, for output messages)
-f, --file-name <name> Asset file name or regex pattern (prefixed with ~) -f, --file-name <name> Asset file name or regex pattern (prefixed with ~)
-b, --binary-name <name> Binary to search for (prefixed with ~ for regex) -b, --binary-name <name> Binary name (supports source:destination form)
-t, --file-type <type> 'archive', 'package', or custom regex (default: archive) -t, --file-type <type> Known: archive|package|linux|macos|targz
Or custom: ~<regex> (end-of-string match) or extension (e.g. zip, .tar.gz)
-p, --install-path <path> Custom installation directory -p, --install-path <path> Custom installation directory
-o, --output-directory <path>
Only download selected asset to the specified directory
-j, --releases-json Download latest release JSON only
--system <name> Override detected system for asset matching
--arch <name> Override detected architecture for asset matching
-k, --token <token> GitHub token -k, --token <token> GitHub token
-d, --debug Enable debug logging -d, --debug Enable debug logging
-h, --help Show this help message -h, --help Show this help message
@@ -178,11 +189,14 @@ If the `token` input is not provided, it will read from the `GITHUB_TOKEN` envir
The list of assets from the latest release is filtered based on the following rules: The list of assets from the latest release is filtered based on the following rules:
1. If neither `file-name` nor `file-type` is provided, the tool defaults to selecting assets that match the following regular expression: `{{SYSTEM}}[_-]{{ARCH}}.*{{EXT_PATTERN}}$`, where: 1. If neither `file-name` nor `file-type` is provided, the tool defaults to selecting assets with an OS-aware extension pattern and this regular expression shape: `{{SYSTEM}}[_-]{{ARCH}}.*{{EXT_PATTERN}}`, where:
- `{{SYSTEM}}` is replaced with the detected operating system regex. - `{{SYSTEM}}` is replaced with the detected operating system regex.
- `{{ARCH}}` is replaced with the detected architecture regex. - `{{ARCH}}` is replaced with the detected architecture regex.
- `{{EXT_PATTERN}}` is a regex pattern defined by the `file-type` input (defaulting to 'archive' if not specified). - `{{EXT_PATTERN}}` is selected by OS:
Linux: `\.(deb|rpm|zip|tar\.gz|tgz)$`
macOS: `\.(pkg|zip|tar\.gz|tgz)$`
other: `\.(zip|tar\.gz|tgz)$`
2. If `file-name` is provided literally, the tool uses it directly to match the asset name by using exact string comparison. 2. If `file-name` is provided literally, the tool uses it directly to match the asset name by using exact string comparison.
@@ -192,7 +206,11 @@ The list of assets from the latest release is filtered based on the following ru
- If it already ends with `$` or includes all three placeholders, the tool uses it as-is to match the asset name using regex. - If it already ends with `$` or includes all three placeholders, the tool uses it as-is to match the asset name using regex.
- If only `{{SYSTEM}}` and `{{ARCH}}` placeholders are included, the tool appends `.*{{EXT_PATTERN}}$`. - If only `{{SYSTEM}}` and `{{ARCH}}` placeholders are included, the tool appends `.*{{EXT_PATTERN}}$`.
4. If `file-type` is not equal to 'archive' or 'package', it is treated as a custom regex pattern to match the file extension. 4. If `file-type` is provided:
- known values are: `archive`, `package`, `linux`, `macos`, `targz`.
- `~<regex>` is treated as a regex and matched at the end of the file name.
- any other value is treated as an extension selector (for example `zip` or `.tar.gz`).
5. The tool applies the constructed regex pattern to filter the assets from the latest release. 5. The tool applies the constructed regex pattern to filter the assets from the latest release.
+1 -2
View File
@@ -12,9 +12,8 @@ inputs:
description: 'The name or regex pattern (prefixed with ~) of the binary to search for within the asset. Defaults to the repository name.' description: 'The name or regex pattern (prefixed with ~) of the binary to search for within the asset. Defaults to the repository name.'
required: false required: false
file-type: file-type:
description: 'The type of the file to be downloaded (archive, package, or custom regex).' description: 'Asset type selector. Known values: archive, package, linux, macos, targz. Custom values: ~<regex> or extension (e.g. zip, .tar.gz).'
required: false required: false
default: 'archive'
update-cache: update-cache:
description: 'How to handle the tool cache (false, true, or always). Defaults to false.' description: 'How to handle the tool cache (false, true, or always). Defaults to false.'
required: false required: false
+19079 -60
View File
File diff suppressed because one or more lines are too long
Vendored Regular → Executable
+48 -1
View File
@@ -1,2 +1,49 @@
#!/usr/bin/env node #!/usr/bin/env node
"use strict";var n=require("util");async function i(t,e){let s=`https://api.github.com/repos/${t}/releases/latest`,r={Accept:"application/vnd.github.v3+json","User-Agent":"setup-github-release-action"};e&&(r.Authorization=`token ${e}`);let o=await fetch(s,{headers:r});if(!o.ok){let a=await o.text();throw new Error(`Failed to fetch latest release for ${t}: ${o.statusText}. ${a}`)}return await o.json()}async function c(){let{positionals:t}=(0,n.parseArgs)({allowPositionals:!0}),e=t[0]||process.env.GITHUB_TOKEN;e||(console.error("Error: No GitHub token provided as an argument or found in GITHUB_TOKEN environment variable."),process.exit(1));try{console.log("Verifying GitHub token..."),await i("actions/checkout",e),console.log("\x1B[32mSuccess: The provided GitHub token is valid and has sufficient permissions to access public repositories.\x1B[0m")}catch(s){console.error("\x1B[31mError: GitHub token verification failed.\x1B[0m"),console.error(`Reason: ${s.message}`),process.exit(1)}}c(); "use strict";
// src/check-token.ts
var import_util = require("util");
// src/core/downloader.ts
function getGithubApiHeaders(token) {
const headers = {
"Accept": "application/vnd.github.v3+json",
"User-Agent": "setup-github-release-action"
};
if (token) {
headers["Authorization"] = `token ${token}`;
}
return headers;
}
async function fetchLatestRelease(repository, token) {
const url = `https://api.github.com/repos/${repository}/releases/latest`;
const headers = getGithubApiHeaders(token);
const response = await fetch(url, { headers });
if (!response.ok) {
const errorBody = await response.text();
throw new Error(`Failed to fetch latest release for ${repository}: ${response.statusText}. ${errorBody}`);
}
return await response.json();
}
// src/check-token.ts
async function run() {
const { positionals } = (0, import_util.parseArgs)({
allowPositionals: true
});
const token = positionals[0] || process.env.GITHUB_TOKEN;
if (!token) {
console.error("Error: No GitHub token provided as an argument or found in GITHUB_TOKEN environment variable.");
process.exit(1);
}
try {
console.log("Verifying GitHub token...");
await fetchLatestRelease("actions/checkout", token);
console.log("\x1B[32mSuccess: The provided GitHub token is valid and has sufficient permissions to access public repositories.\x1B[0m");
} catch (error) {
console.error("\x1B[31mError: GitHub token verification failed.\x1B[0m");
console.error(`Reason: ${error.message}`);
process.exit(1);
}
}
run();
Vendored
-16
View File
@@ -1,16 +0,0 @@
#!/usr/bin/env node
"use strict";var O=Object.create;var z=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var U=Object.getOwnPropertyNames;var D=Object.getPrototypeOf,X=Object.prototype.hasOwnProperty;var Y=(t,e,i,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of U(e))!X.call(t,s)&&s!==i&&z(t,s,{get:()=>e[s],enumerable:!(r=H(e,s))||r.enumerable});return t};var p=(t,e,i)=>(i=t!=null?O(D(t)):{},Y(e||!t||!t.__esModule?z(i,"default",{value:t,enumerable:!0}):i,t));var F=require("util"),f=p(require("path")),l=p(require("fs")),P=p(require("os"));var T=p(require("os")),G={linux:"linux",darwin:"(darwin|macos|mac|osx)",win32:"(windows|win)"},q={x64:"(x86_64|x64|amd64)",arm64:"(aarch64|arm64)"};function M(){let t=T.platform(),e=T.arch();return{system:t,arch:e,systemPattern:G[t]||t,archPattern:q[e]||e}}function j(t,e,i){let{fileName:r,fileType:s="archive"}=i,o;if(s==="archive"?o="\\.(zip|tar\\.gz|tar|tgz|7z)":s==="package"?o="\\.(deb|rpm|pkg)":o=s,r)if(r.startsWith("~")){let a=r.substring(1),c=a.includes("{{SYSTEM}}"),n=a.includes("{{ARCH}}"),m=a.includes("{{EXT_PATTERN}}"),S=a.endsWith("$");!c&&!n&&!m&&!S?a+=".*{{SYSTEM}}[_-]{{ARCH}}.*{{EXT_PATTERN}}$":c&&n&&!m&&!S&&(a+=".*{{EXT_PATTERN}}$");let h=a.replace(/{{SYSTEM}}/g,e.systemPattern).replace(/{{ARCH}}/g,e.archPattern).replace(/{{EXT_PATTERN}}/g,o),b=new RegExp(h,"i"),u=t.filter(w=>b.test(w.name));if(u.length===0)throw new Error(`No assets matched the regex: ${h}`);if(u.length>1)throw new Error(`Multiple assets matched the criteria: ${u.map(w=>w.name).join(", ")}`);return u[0]}else{let a=t.find(c=>c.name===r);if(!a)throw new Error(`No asset found matching the exact name: ${r}`);return a}else{let a=`${e.systemPattern}[_-]${e.archPattern}.*${o}$`,c=new RegExp(a,"i"),n=t.filter(m=>c.test(m.name));if(n.length===0)throw new Error(`No assets matched the default criteria: ${a}`);if(n.length>1)throw new Error(`Multiple assets matched the default criteria: ${n.map(m=>m.name).join(", ")}`);return n[0]}}var A=p(require("fs")),_=p(require("path"));function I(t,e,i,r){let s=A.readdirSync(t);i&&(r(`Searching for binary in ${t}...`),s.forEach(o=>r(` - ${o}`)));for(let o of s){let a=_.join(t,o);if(A.statSync(a).isDirectory()){let n=I(a,e,i,r);if(n)return n}else{let n=!1;if(e instanceof RegExp?n=e.test(o):(n=o===e,!n&&process.platform==="win32"&&!e.toLowerCase().endsWith(".exe")&&(n=o.toLowerCase()===`${e.toLowerCase()}.exe`)),n)return a}}}async function W(t,e){let i=`https://api.github.com/repos/${t}/releases/latest`,r={Accept:"application/vnd.github.v3+json","User-Agent":"setup-github-release-action"};e&&(r.Authorization=`token ${e}`);let s=await fetch(i,{headers:r});if(!s.ok){let o=await s.text();throw new Error(`Failed to fetch latest release for ${t}: ${s.statusText}. ${o}`)}return await s.json()}async function L(t,e,i){let r={"User-Agent":"setup-github-release-action"};i&&(r.Authorization=`token ${i}`);let s=await fetch(t,{headers:r});if(!s.ok)throw new Error(`Failed to download asset: ${s.statusText}`);let o=await import("fs"),{Readable:a}=await import("stream"),{finished:c}=await import("stream/promises"),n=o.createWriteStream(e);await c(a.fromWeb(s.body).pipe(n))}var x=require("child_process"),y=p(require("path")),E=p(require("fs"));async function B(t,e){let i=y.extname(t).toLowerCase(),r=y.basename(t).toLowerCase();if(E.existsSync(e)||E.mkdirSync(e,{recursive:!0}),r.endsWith(".tar.gz")||r.endsWith(".tgz")||r.endsWith(".tar")){let o=(0,x.spawnSync)("tar",["-xf",t,"-C",e]);if(o.status!==0)throw new Error(`tar failed with status ${o.status}: ${o.stderr.toString()}`)}else if(r.endsWith(".zip"))if(process.platform==="win32"){if((0,x.spawnSync)("tar",["-xf",t,"-C",e]).status===0)return;let o=t.replace(/'/g,"''"),a=e.replace(/'/g,"''"),c=`Add-Type -AssemblyName System.IO.Compression.FileSystem; [System.IO.Compression.ZipFile]::ExtractToDirectory('${o}', '${a}')`;for(let n of["pwsh","powershell"])if((0,x.spawnSync)(n,["-NoProfile","-ExecutionPolicy","Bypass","-Command",c]).status===0)return;throw new Error("Extraction failed: Both tar and PowerShell fallback failed. Make sure your system can extract ZIP files.")}else{let s=(0,x.spawnSync)("unzip",["-q",t,"-d",e]);if(s.status!==0)throw new Error(`unzip failed with status ${s.status}: ${s.stderr.toString()}`)}else if(r.endsWith(".7z")){let s=(0,x.spawnSync)("7z",["x",t,`-o${e}`,"-y"]);if(s.status!==0)throw new Error(`7z failed with status ${s.status}. Make sure 7z is installed.`)}else{let s=y.join(e,y.basename(t));E.copyFileSync(t,s)}}async function Z(){let{values:t,positionals:e}=(0,F.parseArgs)({options:{"file-name":{type:"string",short:"f"},"binary-name":{type:"string",short:"b"},"file-type":{type:"string",short:"t",default:"archive"},"install-path":{type:"string",short:"p"},token:{type:"string",short:"k"},debug:{type:"boolean",short:"d",default:!1},help:{type:"boolean",short:"h"}},allowPositionals:!0});(t.help||e.length===0)&&(console.log(`
Usage: install-github-release [options] <repository>
Arguments:
repository The GitHub repository (owner/repo)
Options:
-f, --file-name <name> Asset file name or regex pattern (prefixed with ~)
-b, --binary-name <name> Binary to search for (prefixed with ~ for regex)
-t, --file-type <type> 'archive', 'package', or custom regex (default: archive)
-p, --install-path <path> Custom installation directory
-k, --token <token> GitHub token
-d, --debug Enable debug logging
-h, --help Show this help message
`),process.exit(0));let i=e[0];i||(console.error("Error: Repository is required."),process.exit(1));let r=t["file-name"],s=t["binary-name"],o=t["file-type"],a=!!t.debug,c=t.token||process.env.GITHUB_TOKEN;try{let n=M(),m=i.split("/").pop()||i;console.log(`Fetching latest release for ${i}...`);let S=await W(i,c),h=j(S.assets,n,{fileName:r,fileType:o});console.log(`Selected asset: ${h.name}`);let b=l.mkdtempSync(f.join(P.tmpdir(),"setup-gh-release-")),u=f.join(b,h.name);console.log(`Downloading ${h.name}...`),await L(h.browser_download_url,u,c);let w=f.join(b,"extract");console.log(`Extracting ${h.name}...`),await B(u,w);let R=s||m,k;R.startsWith("~")?k=new RegExp(R.substring(1),"i"):k=R;let C=I(w,k,a,console.log);if(!C)throw new Error(`Could not find binary "${R}" in the extracted asset.`);let g;if(t["install-path"])g=f.resolve(t["install-path"]);else if(process.platform==="win32"){let d=process.env.LOCALAPPDATA||f.join(P.homedir(),"AppData","Local");g=f.join(d,"bin")}else if(process.getuid&&process.getuid()===0)g="/usr/local/bin";else{let N=f.join(P.homedir(),"bin");l.existsSync(N)?g=N:g="/usr/local/bin"}l.existsSync(g)||l.mkdirSync(g,{recursive:!0});let v=f.basename(C),$=f.join(g,v);console.log(`Installing ${v} to ${$}...`);try{l.copyFileSync(C,$)}catch(d){throw d.code==="EBUSY"?new Error(`The file ${$} is currently in use. Please close any running instances and try again.`):d.code==="EACCES"||d.code==="EPERM"?new Error(`Permission denied while installing to ${$}. Try running with sudo or as administrator, or use -p to specify a custom path.`):d}process.platform!=="win32"&&l.chmodSync($,"755"),l.rmSync(b,{recursive:!0,force:!0}),console.log("Installation successful!")}catch(n){console.error(`Error: ${n.message}`),process.exit(1)}}Z();
+25084 -61
View File
File diff suppressed because one or more lines are too long
+205 -163
View File
@@ -1,78 +1,84 @@
{ {
"name": "setup-github-release", "name": "install-github-release",
"version": "1.0.0", "version": "1.0.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "setup-github-release", "name": "install-github-release",
"version": "1.0.0", "version": "1.0.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^1.11.0", "@actions/core": "latest",
"@actions/tool-cache": "^2.0.2" "@actions/tool-cache": "latest",
"commander": "latest",
"minimatch": "latest"
},
"bin": {
"check-github-token": "dist/check-token.js",
"install-github-release": "dist/cli.js"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^25.0.0", "@types/node": "^24",
"esbuild": "^0.27.2", "esbuild": "latest",
"typescript": "^5.9.0" "typescript": "latest"
}, },
"engines": { "engines": {
"node": ">=24" "node": ">=24"
} }
}, },
"node_modules/@actions/core": { "node_modules/@actions/core": {
"version": "1.11.1", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", "resolved": "https://registry.npmjs.org/@actions/core/-/core-3.0.0.tgz",
"integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==", "integrity": "sha512-zYt6cz+ivnTmiT/ksRVriMBOiuoUpDCJJlZ5KPl2/FRdvwU3f7MPh9qftvbkXJThragzUZieit2nyHUyw53Seg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/exec": "^1.1.1", "@actions/exec": "^3.0.0",
"@actions/http-client": "^2.0.1" "@actions/http-client": "^4.0.0"
} }
}, },
"node_modules/@actions/exec": { "node_modules/@actions/exec": {
"version": "1.1.1", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-3.0.0.tgz",
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", "integrity": "sha512-6xH/puSoNBXb72VPlZVm7vQ+svQpFyA96qdDBvhB8eNZOE8LtPf9L4oAsfzK/crCL8YZ+19fKYVnM63Sl+Xzlw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/io": "^1.0.1" "@actions/io": "^3.0.2"
} }
}, },
"node_modules/@actions/http-client": { "node_modules/@actions/http-client": {
"version": "2.2.3", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-4.0.0.tgz",
"integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", "integrity": "sha512-QuwPsgVMsD6qaPD57GLZi9sqzAZCtiJT8kVBCDpLtxhL5MydQ4gS+DrejtZZPdIYyB1e95uCK9Luyds7ybHI3g==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"tunnel": "^0.0.6", "tunnel": "^0.0.6",
"undici": "^5.25.4" "undici": "^6.23.0"
} }
}, },
"node_modules/@actions/io": { "node_modules/@actions/io": {
"version": "1.1.3", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", "resolved": "https://registry.npmjs.org/@actions/io/-/io-3.0.2.tgz",
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==", "integrity": "sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@actions/tool-cache": { "node_modules/@actions/tool-cache": {
"version": "2.0.2", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-2.0.2.tgz", "resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-4.0.0.tgz",
"integrity": "sha512-fBhNNOWxuoLxztQebpOaWu6WeVmuwa77Z+DxIZ1B+OYvGkGQon6kTVg6Z32Cb13WCuw0szqonK+hh03mJV7Z6w==", "integrity": "sha512-L8P9HbXvpvqjZDveb/fdsa55IVC0trfPgQ4ZwGo6r5af6YDVdM9vMGPZ7rgY2fAT9gGj4PSYd6bYlg3p3jD78A==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^1.11.1", "@actions/core": "^3.0.0",
"@actions/exec": "^1.0.0", "@actions/exec": "^3.0.0",
"@actions/http-client": "^2.0.1", "@actions/http-client": "^4.0.0",
"@actions/io": "^1.1.1", "@actions/io": "^3.0.0",
"semver": "^6.1.0" "semver": "^7.7.3"
} }
}, },
"node_modules/@esbuild/aix-ppc64": { "node_modules/@esbuild/aix-ppc64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz",
"integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", "integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
@@ -87,9 +93,9 @@
} }
}, },
"node_modules/@esbuild/android-arm": { "node_modules/@esbuild/android-arm": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz",
"integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", "integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -104,9 +110,9 @@
} }
}, },
"node_modules/@esbuild/android-arm64": { "node_modules/@esbuild/android-arm64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz",
"integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", "integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -121,9 +127,9 @@
} }
}, },
"node_modules/@esbuild/android-x64": { "node_modules/@esbuild/android-x64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz",
"integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", "integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -138,9 +144,9 @@
} }
}, },
"node_modules/@esbuild/darwin-arm64": { "node_modules/@esbuild/darwin-arm64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz",
"integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -155,9 +161,9 @@
} }
}, },
"node_modules/@esbuild/darwin-x64": { "node_modules/@esbuild/darwin-x64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz",
"integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", "integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -172,9 +178,9 @@
} }
}, },
"node_modules/@esbuild/freebsd-arm64": { "node_modules/@esbuild/freebsd-arm64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz",
"integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", "integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -189,9 +195,9 @@
} }
}, },
"node_modules/@esbuild/freebsd-x64": { "node_modules/@esbuild/freebsd-x64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz",
"integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", "integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -206,9 +212,9 @@
} }
}, },
"node_modules/@esbuild/linux-arm": { "node_modules/@esbuild/linux-arm": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz",
"integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", "integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -223,9 +229,9 @@
} }
}, },
"node_modules/@esbuild/linux-arm64": { "node_modules/@esbuild/linux-arm64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz",
"integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", "integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -240,9 +246,9 @@
} }
}, },
"node_modules/@esbuild/linux-ia32": { "node_modules/@esbuild/linux-ia32": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz",
"integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", "integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@@ -257,9 +263,9 @@
} }
}, },
"node_modules/@esbuild/linux-loong64": { "node_modules/@esbuild/linux-loong64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz",
"integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", "integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==",
"cpu": [ "cpu": [
"loong64" "loong64"
], ],
@@ -274,9 +280,9 @@
} }
}, },
"node_modules/@esbuild/linux-mips64el": { "node_modules/@esbuild/linux-mips64el": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz",
"integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", "integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==",
"cpu": [ "cpu": [
"mips64el" "mips64el"
], ],
@@ -291,9 +297,9 @@
} }
}, },
"node_modules/@esbuild/linux-ppc64": { "node_modules/@esbuild/linux-ppc64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz",
"integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", "integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
@@ -308,9 +314,9 @@
} }
}, },
"node_modules/@esbuild/linux-riscv64": { "node_modules/@esbuild/linux-riscv64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz",
"integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", "integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
@@ -325,9 +331,9 @@
} }
}, },
"node_modules/@esbuild/linux-s390x": { "node_modules/@esbuild/linux-s390x": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz",
"integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", "integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==",
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
@@ -342,9 +348,9 @@
} }
}, },
"node_modules/@esbuild/linux-x64": { "node_modules/@esbuild/linux-x64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz",
"integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", "integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -359,9 +365,9 @@
} }
}, },
"node_modules/@esbuild/netbsd-arm64": { "node_modules/@esbuild/netbsd-arm64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz",
"integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", "integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -376,9 +382,9 @@
} }
}, },
"node_modules/@esbuild/netbsd-x64": { "node_modules/@esbuild/netbsd-x64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz",
"integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", "integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -393,9 +399,9 @@
} }
}, },
"node_modules/@esbuild/openbsd-arm64": { "node_modules/@esbuild/openbsd-arm64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz",
"integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", "integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -410,9 +416,9 @@
} }
}, },
"node_modules/@esbuild/openbsd-x64": { "node_modules/@esbuild/openbsd-x64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz",
"integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", "integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -427,9 +433,9 @@
} }
}, },
"node_modules/@esbuild/openharmony-arm64": { "node_modules/@esbuild/openharmony-arm64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz",
"integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", "integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -444,9 +450,9 @@
} }
}, },
"node_modules/@esbuild/sunos-x64": { "node_modules/@esbuild/sunos-x64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz",
"integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", "integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -461,9 +467,9 @@
} }
}, },
"node_modules/@esbuild/win32-arm64": { "node_modules/@esbuild/win32-arm64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz",
"integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", "integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -478,9 +484,9 @@
} }
}, },
"node_modules/@esbuild/win32-ia32": { "node_modules/@esbuild/win32-ia32": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz",
"integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", "integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@@ -495,9 +501,9 @@
} }
}, },
"node_modules/@esbuild/win32-x64": { "node_modules/@esbuild/win32-x64": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz",
"integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -511,29 +517,50 @@
"node": ">=18" "node": ">=18"
} }
}, },
"node_modules/@fastify/busboy": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
"integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==",
"license": "MIT",
"engines": {
"node": ">=14"
}
},
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "25.0.6", "version": "24.12.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.6.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz",
"integrity": "sha512-NNu0sjyNxpoiW3YuVFfNz7mxSQ+S4X2G28uqg2s+CzoqoQjLPsWSbsFFyztIAqt2vb8kfEAsJNepMGPTxFDx3Q==", "integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"undici-types": "~7.16.0" "undici-types": "~7.16.0"
} }
}, },
"node_modules/balanced-match": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
"license": "MIT",
"engines": {
"node": "18 || 20 || >=22"
}
},
"node_modules/brace-expansion": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
"integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
"license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
},
"engines": {
"node": "18 || 20 || >=22"
}
},
"node_modules/commander": {
"version": "14.0.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz",
"integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==",
"license": "MIT",
"engines": {
"node": ">=20"
}
},
"node_modules/esbuild": { "node_modules/esbuild": {
"version": "0.27.2", "version": "0.28.0",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz",
"integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==",
"dev": true, "dev": true,
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT", "license": "MIT",
@@ -544,41 +571,59 @@
"node": ">=18" "node": ">=18"
}, },
"optionalDependencies": { "optionalDependencies": {
"@esbuild/aix-ppc64": "0.27.2", "@esbuild/aix-ppc64": "0.28.0",
"@esbuild/android-arm": "0.27.2", "@esbuild/android-arm": "0.28.0",
"@esbuild/android-arm64": "0.27.2", "@esbuild/android-arm64": "0.28.0",
"@esbuild/android-x64": "0.27.2", "@esbuild/android-x64": "0.28.0",
"@esbuild/darwin-arm64": "0.27.2", "@esbuild/darwin-arm64": "0.28.0",
"@esbuild/darwin-x64": "0.27.2", "@esbuild/darwin-x64": "0.28.0",
"@esbuild/freebsd-arm64": "0.27.2", "@esbuild/freebsd-arm64": "0.28.0",
"@esbuild/freebsd-x64": "0.27.2", "@esbuild/freebsd-x64": "0.28.0",
"@esbuild/linux-arm": "0.27.2", "@esbuild/linux-arm": "0.28.0",
"@esbuild/linux-arm64": "0.27.2", "@esbuild/linux-arm64": "0.28.0",
"@esbuild/linux-ia32": "0.27.2", "@esbuild/linux-ia32": "0.28.0",
"@esbuild/linux-loong64": "0.27.2", "@esbuild/linux-loong64": "0.28.0",
"@esbuild/linux-mips64el": "0.27.2", "@esbuild/linux-mips64el": "0.28.0",
"@esbuild/linux-ppc64": "0.27.2", "@esbuild/linux-ppc64": "0.28.0",
"@esbuild/linux-riscv64": "0.27.2", "@esbuild/linux-riscv64": "0.28.0",
"@esbuild/linux-s390x": "0.27.2", "@esbuild/linux-s390x": "0.28.0",
"@esbuild/linux-x64": "0.27.2", "@esbuild/linux-x64": "0.28.0",
"@esbuild/netbsd-arm64": "0.27.2", "@esbuild/netbsd-arm64": "0.28.0",
"@esbuild/netbsd-x64": "0.27.2", "@esbuild/netbsd-x64": "0.28.0",
"@esbuild/openbsd-arm64": "0.27.2", "@esbuild/openbsd-arm64": "0.28.0",
"@esbuild/openbsd-x64": "0.27.2", "@esbuild/openbsd-x64": "0.28.0",
"@esbuild/openharmony-arm64": "0.27.2", "@esbuild/openharmony-arm64": "0.28.0",
"@esbuild/sunos-x64": "0.27.2", "@esbuild/sunos-x64": "0.28.0",
"@esbuild/win32-arm64": "0.27.2", "@esbuild/win32-arm64": "0.28.0",
"@esbuild/win32-ia32": "0.27.2", "@esbuild/win32-ia32": "0.28.0",
"@esbuild/win32-x64": "0.27.2" "@esbuild/win32-x64": "0.28.0"
}
},
"node_modules/minimatch": {
"version": "10.2.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
"integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
"license": "BlueOak-1.0.0",
"dependencies": {
"brace-expansion": "^5.0.5"
},
"engines": {
"node": "18 || 20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
} }
}, },
"node_modules/semver": { "node_modules/semver": {
"version": "6.3.1", "version": "7.7.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
"license": "ISC", "license": "ISC",
"bin": { "bin": {
"semver": "bin/semver.js" "semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
} }
}, },
"node_modules/tunnel": { "node_modules/tunnel": {
@@ -591,9 +636,9 @@
} }
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "5.9.3", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.2.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {
@@ -605,15 +650,12 @@
} }
}, },
"node_modules/undici": { "node_modules/undici": {
"version": "5.29.0", "version": "6.24.1",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", "resolved": "https://registry.npmjs.org/undici/-/undici-6.24.1.tgz",
"integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", "integrity": "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==",
"license": "MIT", "license": "MIT",
"dependencies": {
"@fastify/busboy": "^2.0.0"
},
"engines": { "engines": {
"node": ">=14.0" "node": ">=18.17"
} }
}, },
"node_modules/undici-types": { "node_modules/undici-types": {
+14 -18
View File
@@ -8,35 +8,31 @@
"check-github-token": "dist/check-token.js" "check-github-token": "dist/check-token.js"
}, },
"scripts": { "scripts": {
"build:action": "esbuild src/index.ts --bundle --platform=node --target=node24 --outfile=dist/index.js --minify", "build:action": "esbuild src/index.ts --bundle --platform=node --target=node24 --outfile=dist/index.js",
"build:cli": "esbuild src/cli.ts --bundle --platform=node --target=node24 --outfile=dist/cli.js --minify --banner:js=\"#!/usr/bin/env node\"", "build:cli": "esbuild src/cli.ts --bundle --platform=node --target=node24 --outfile=dist/cli.js --banner:js=\"#!/usr/bin/env node\" && chmod +x dist/cli.js",
"build:check-token": "esbuild src/check-token.ts --bundle --platform=node --target=node24 --outfile=dist/check-token.js --minify --banner:js=\"#!/usr/bin/env node\"", "build:check-token": "esbuild src/check-token.ts --bundle --platform=node --target=node24 --outfile=dist/check-token.js --banner:js=\"#!/usr/bin/env node\" && chmod +x dist/check-token.js",
"build:check-token-action": "esbuild src/check-token-action.ts --bundle --platform=node --target=node24 --outfile=dist/check-token-action.js --minify", "build:check-token-action": "esbuild src/check-token-action.ts --bundle --platform=node --target=node24 --outfile=dist/check-token-action.js",
"build": "npm run build:action && npm run build:cli && npm run build:check-token && npm run build:check-token-action", "build": "npm run build:action && npm run build:cli && npm run build:check-token && npm run build:check-token-action"
"format": "prettier --write '**/*.ts'",
"format-check": "prettier --check '**/*.ts'",
"lint": "eslint src/**/*.ts",
"package": "npm run build",
"test": "jest",
"all": "npm run format && npm run lint && npm run test && npm run package"
}, },
"keywords": [ "keywords": [
"actions", "actions",
"node", "node",
"setup" "setup"
], ],
"author": "", "author": "Sławomir Koszewski",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=24" "node": "24.x"
}, },
"dependencies": { "dependencies": {
"@actions/core": "^1.11.0", "@actions/core": "3.0.0",
"@actions/tool-cache": "^2.0.2" "@actions/tool-cache": "4.0.0",
"commander": "14.0.3",
"minimatch": "10.2.5"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^25.0.0", "@types/node": "^24",
"esbuild": "^0.27.2", "esbuild": "0.28.0",
"typescript": "^5.9.0" "typescript": "6.0.2"
} }
} }
+185 -100
View File
@@ -1,151 +1,236 @@
import { parseArgs } from 'util';
import * as path from 'path'; import * as path from 'path';
import * as fs from 'fs'; import * as fs from 'fs';
import * as os from 'os'; import * as os from 'os';
import { Command } from 'commander';
import { getPlatformInfo } from './core/platform'; import { getPlatformInfo } from './core/platform';
import { getMatchingAsset } from './core/matcher'; import { getMatchingAsset } from './core/matcher';
import { findBinary } from './core/finder'; import { findBinary } from './core/finder';
import { fetchLatestRelease, downloadAsset } from './core/downloader'; import { fetchLatestRelease, fetchLatestReleaseRaw, downloadAsset } from './core/downloader';
import { extractAsset } from './core/extractor'; import { extractAsset } from './core/extractor';
import { installSystemPackage } from './core/installer';
async function run() { interface CliOptions {
const { values, positionals } = parseArgs({ appName?: string;
options: { fileName?: string;
'file-name': { type: 'string', short: 'f' }, binaryName?: string;
'binary-name': { type: 'string', short: 'b' }, fileType?: string;
'file-type': { type: 'string', short: 't', default: 'archive' }, installPath?: string;
'install-path': { type: 'string', short: 'p' }, outputDirectory?: string;
'token': { type: 'string', short: 'k' }, releasesJsonOnly: boolean;
'debug': { type: 'boolean', short: 'd', default: false }, listOnly: boolean;
'help': { type: 'boolean', short: 'h' } token?: string;
}, debug: boolean;
allowPositionals: true dryRun: boolean;
}); systemOverride?: string;
archOverride?: string;
listRepo?: string;
positionals: string[];
}
if (values.help || positionals.length === 0) { function validateOutputDirectory(outputDirectory: string): string {
console.log(` const resolvedPath = path.resolve(outputDirectory);
Usage: install-github-release [options] <repository> if (!fs.existsSync(resolvedPath) || !fs.statSync(resolvedPath).isDirectory()) {
throw new Error(`Output directory "${resolvedPath}" does not exist.`);
}
return resolvedPath;
}
Arguments: function getInstallDir(installPath?: string): string {
repository The GitHub repository (owner/repo) if (installPath) {
return path.resolve(installPath);
Options:
-f, --file-name <name> Asset file name or regex pattern (prefixed with ~)
-b, --binary-name <name> Binary to search for (prefixed with ~ for regex)
-t, --file-type <type> 'archive', 'package', or custom regex (default: archive)
-p, --install-path <path> Custom installation directory
-k, --token <token> GitHub token
-d, --debug Enable debug logging
-h, --help Show this help message
`);
process.exit(0);
} }
const repository = positionals[0]; if (process.platform === 'win32') {
const localAppData = process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
return path.join(localAppData, 'bin');
}
const isRoot = process.getuid && process.getuid() === 0;
if (isRoot) {
return '/usr/local/bin';
}
const homeBin = path.join(os.homedir(), 'bin');
if (fs.existsSync(homeBin)) {
return homeBin;
}
return '/usr/local/bin';
}
async function run() {
let tempDir: string | undefined;
const program = new Command();
program
.name('install-github-release')
.usage('[options] <repository>')
.argument('[repository]', 'The GitHub repository (owner/repo)')
.option('--dry-run', 'Run in test mode')
.option('-l, --list [repository]', 'List available assets from latest release and exit')
.option('-a, --app-name <name>', 'Application name (optional, for output messages)')
.option('-f, --file-name <name>', 'Asset file name or regex pattern (prefixed with ~)')
.option('-b, --binary-name <name>', 'Binary name (supports source:destination form)')
.option('-t, --file-type <type>', 'Known: archive|package|linux|macos|targz; custom: ~<regex> or extension')
.option('-p, --install-path <path>', 'Custom installation directory')
.option('-o, --output-directory <path>', 'Only download selected asset to the specified directory')
.option('-j, --releases-json', 'Download latest release JSON only')
.option('--system <name>', 'Override detected system for asset matching')
.option('--arch <name>', 'Override detected architecture for asset matching')
.option('-k, --token <token>', 'GitHub token')
.option('-d, --debug', 'Enable debug logging')
.allowUnknownOption(false);
const cleanupTempDir = () => {
if (tempDir && fs.existsSync(tempDir)) {
fs.rmSync(tempDir, { recursive: true, force: true });
}
};
program.parse(process.argv);
const parsedOptions = program.opts();
const rawFileType = parsedOptions.fileType;
const fileType = typeof rawFileType === 'string' ? rawFileType.trim() : undefined;
if (rawFileType !== undefined && !fileType) {
throw new Error(`Unknown asset type: ${rawFileType}`);
}
const listValue = parsedOptions.list as string | boolean | undefined;
const options: CliOptions = {
appName: parsedOptions.appName as string | undefined,
fileName: parsedOptions.fileName as string | undefined,
binaryName: parsedOptions.binaryName as string | undefined,
fileType,
installPath: parsedOptions.installPath as string | undefined,
outputDirectory: parsedOptions.outputDirectory as string | undefined,
releasesJsonOnly: Boolean(parsedOptions.releasesJson),
listOnly: listValue !== undefined,
token: parsedOptions.token as string | undefined,
debug: Boolean(parsedOptions.debug),
dryRun: Boolean(parsedOptions.dryRun),
systemOverride: parsedOptions.system as string | undefined,
archOverride: parsedOptions.arch as string | undefined,
listRepo: typeof listValue === 'string' ? listValue : undefined,
positionals: program.args
};
const repository = options.listRepo || options.positionals[0];
if (!repository) { if (!repository) {
console.error('Error: Repository is required.'); program.outputHelp();
process.exit(1); process.exit(1);
} }
const fileNameInput = values['file-name']; const token = options.token;
const binaryInput = values['binary-name'];
const fileType = values['file-type']; if (options.listOnly) {
const debug = !!values.debug; const release = await fetchLatestRelease(repository, token);
const token = values.token || process.env.GITHUB_TOKEN; release.assets.forEach((asset) => console.log(`- ${asset.browser_download_url}`));
process.exit(0);
}
try {
const platformInfo = getPlatformInfo();
const toolName = repository.split('/').pop() || repository; const toolName = repository.split('/').pop() || repository;
const appName = options.appName || (toolName.charAt(0).toUpperCase() + toolName.slice(1));
const binaryOption = options.binaryName || toolName;
const [binarySource, binaryDestination] = binaryOption.includes(':')
? [binaryOption.split(':')[0], binaryOption.split(':')[1]]
: [binaryOption, binaryOption];
if (options.releasesJsonOnly) {
const rawRelease = await fetchLatestReleaseRaw(repository, token);
const outputBase = binaryDestination || toolName;
const outputName = `${outputBase}.releases.json`;
const outputPath = options.outputDirectory
? path.join(validateOutputDirectory(options.outputDirectory), outputName)
: outputName;
fs.writeFileSync(outputPath, rawRelease, 'utf8');
console.log(`Downloaded GitHub releases to ${outputPath}.`);
process.exit(0);
}
const platformInfo = getPlatformInfo({
system: options.systemOverride,
arch: options.archOverride
});
console.log(`Fetching latest release for ${repository}...`); console.log(`Fetching latest release for ${repository}...`);
const release = await fetchLatestRelease(repository, token); const release = await fetchLatestRelease(repository, token);
const asset = getMatchingAsset(release.assets, platformInfo, { const asset = getMatchingAsset(release.assets, platformInfo, options.fileName, options.fileType, options.dryRun);
fileName: fileNameInput,
fileType: fileType
});
console.log(`Selected asset: ${asset.name}`); const version = release.tag_name.replace(/^v/i, '');
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'setup-gh-release-')); const downloadUrl = asset.browser_download_url;
console.log(`Will download '${appName}' version: ${version}`);
console.log(`Download URL: "${downloadUrl}".`);
if (options.dryRun) {
process.exit(0);
}
if (options.outputDirectory) {
const outputDir = validateOutputDirectory(options.outputDirectory);
const outputPath = path.join(outputDir, path.basename(downloadUrl));
console.log(`Downloading '${appName}' version ${version} to '${outputPath}'...`);
await downloadAsset(downloadUrl, outputPath, token);
process.exit(0);
}
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'setup-gh-release-'));
process.once('exit', cleanupTempDir);
const downloadPath = path.join(tempDir, asset.name); const downloadPath = path.join(tempDir, asset.name);
await downloadAsset(downloadUrl, downloadPath, token);
console.log(`Downloading ${asset.name}...`); if (/\.(deb|pkg|rpm)$/i.test(asset.name)) {
await downloadAsset(asset.browser_download_url, downloadPath, token); installSystemPackage(downloadPath);
console.log('Installation successful!');
process.exit(0);
}
const extractDir = path.join(tempDir, 'extract'); const extractDir = path.join(tempDir, 'extract');
console.log(`Extracting ${asset.name}...`); console.log(`Extracting ${asset.name}...`);
await extractAsset(downloadPath, extractDir); await extractAsset(downloadPath, extractDir);
const binaryName = binaryInput || toolName; let binaryPattern: string;
let binaryPattern: string | RegExp; if (binarySource.startsWith('~')) {
if (binaryName.startsWith('~')) { const binaryRegex = binarySource
binaryPattern = new RegExp(binaryName.substring(1), 'i'); .substring(1)
.replace(/{{SYSTEM}}/g, platformInfo.systemPattern)
.replace(/{{ARCH}}/g, platformInfo.archPattern);
binaryPattern = `~${binaryRegex}`;
} else { } else {
binaryPattern = binaryName; binaryPattern = binarySource
.replace(/{{SYSTEM}}/g, platformInfo.system)
.replace(/{{ARCH}}/g, platformInfo.arch);
} }
const binaryPath = findBinary(extractDir, binaryPattern, debug, console.log); const binaryPath = findBinary(extractDir, binaryPattern, options.debug, console.log);
if (!binaryPath) { if (!binaryPath) {
throw new Error(`Could not find binary "${binaryName}" in the extracted asset.`); throw new Error(`Could not find binary "${binarySource}" in the extracted asset.`);
}
// Determine install directory
let installDir: string;
if (values['install-path']) {
installDir = path.resolve(values['install-path']);
} else {
if (process.platform === 'win32') {
const localAppData = process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
installDir = path.join(localAppData, 'bin');
} else {
const isRoot = process.getuid && process.getuid() === 0;
if (isRoot) {
installDir = '/usr/local/bin';
} else {
const homeBin = path.join(os.homedir(), 'bin');
if (fs.existsSync(homeBin)) {
installDir = homeBin;
} else {
installDir = '/usr/local/bin';
}
}
}
} }
const installDir = getInstallDir(options.installPath);
if (!fs.existsSync(installDir)) { if (!fs.existsSync(installDir)) {
fs.mkdirSync(installDir, { recursive: true }); fs.mkdirSync(installDir, { recursive: true });
} }
const finalName = path.basename(binaryPath); const finalName = binaryDestination || path.basename(binaryPath);
const destPath = path.join(installDir, finalName); const destPath = path.join(installDir, finalName);
console.log(`Installing ${finalName} to ${destPath}...`); console.log(`Installing ${finalName} to ${destPath}...`);
try {
fs.copyFileSync(binaryPath, destPath); fs.copyFileSync(binaryPath, destPath);
} catch (err: any) {
if (err.code === 'EBUSY') {
throw new Error(`The file ${destPath} is currently in use. Please close any running instances and try again.`);
}
if (err.code === 'EACCES' || err.code === 'EPERM') {
throw new Error(`Permission denied while installing to ${destPath}. Try running with sudo or as administrator, or use -p to specify a custom path.`);
}
throw err;
}
if (process.platform !== 'win32') { if (process.platform !== 'win32') {
fs.chmodSync(destPath, '755'); fs.chmodSync(destPath, '755');
} }
// Cleanup
fs.rmSync(tempDir, { recursive: true, force: true });
console.log('Installation successful!'); console.log('Installation successful!');
process.exit(0);
} catch (error: any) {
console.error(`Error: ${error.message}`);
process.exit(1);
}
} }
run(); void run().catch((error: unknown) => {
if (error instanceof Error && error.message) {
console.error(`Error: ${error.message}`);
} else {
console.error('Error: Unknown failure.');
}
process.exit(1);
});
+19 -5
View File
@@ -1,6 +1,3 @@
import { getMatchingAsset } from './matcher';
import { PlatformInfo } from './platform';
export interface ReleaseAsset { export interface ReleaseAsset {
name: string; name: string;
browser_download_url: string; browser_download_url: string;
@@ -11,8 +8,7 @@ export interface ReleaseInfo {
assets: ReleaseAsset[]; assets: ReleaseAsset[];
} }
export async function fetchLatestRelease(repository: string, token?: string): Promise<ReleaseInfo> { function getGithubApiHeaders(token?: string): Record<string, string> {
const url = `https://api.github.com/repos/${repository}/releases/latest`;
const headers: Record<string, string> = { const headers: Record<string, string> = {
'Accept': 'application/vnd.github.v3+json', 'Accept': 'application/vnd.github.v3+json',
'User-Agent': 'setup-github-release-action' 'User-Agent': 'setup-github-release-action'
@@ -20,6 +16,12 @@ export async function fetchLatestRelease(repository: string, token?: string): Pr
if (token) { if (token) {
headers['Authorization'] = `token ${token}`; headers['Authorization'] = `token ${token}`;
} }
return headers;
}
export async function fetchLatestRelease(repository: string, token?: string): Promise<ReleaseInfo> {
const url = `https://api.github.com/repos/${repository}/releases/latest`;
const headers = getGithubApiHeaders(token);
const response = await fetch(url, { headers }); const response = await fetch(url, { headers });
if (!response.ok) { if (!response.ok) {
@@ -30,6 +32,18 @@ export async function fetchLatestRelease(repository: string, token?: string): Pr
return await response.json() as ReleaseInfo; return await response.json() as ReleaseInfo;
} }
export async function fetchLatestReleaseRaw(repository: string, token?: string): Promise<string> {
const url = `https://api.github.com/repos/${repository}/releases/latest`;
const headers = getGithubApiHeaders(token);
const response = await fetch(url, { headers });
const body = await response.text();
if (!response.ok) {
throw new Error(`Failed to fetch latest release for ${repository}: ${response.statusText}. ${body}`);
}
return body;
}
export async function downloadAsset(url: string, destPath: string, token?: string): Promise<void> { export async function downloadAsset(url: string, destPath: string, token?: string): Promise<void> {
const headers: Record<string, string> = { const headers: Record<string, string> = {
'User-Agent': 'setup-github-release-action' 'User-Agent': 'setup-github-release-action'
+4 -3
View File
@@ -1,7 +1,8 @@
import * as fs from 'fs'; import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';
export function findBinary(dir: string, pattern: string | RegExp, debug: boolean, logger: (msg: string) => void): string | undefined { export function findBinary(dir: string, pattern: string, debug: boolean, logger: (msg: string) => void): string | undefined {
const regex = pattern.startsWith('~') ? new RegExp(pattern.substring(1), 'i') : undefined;
const items = fs.readdirSync(dir); const items = fs.readdirSync(dir);
if (debug) { if (debug) {
logger(`Searching for binary in ${dir}...`); logger(`Searching for binary in ${dir}...`);
@@ -16,8 +17,8 @@ export function findBinary(dir: string, pattern: string | RegExp, debug: boolean
if (found) return found; if (found) return found;
} else { } else {
let isMatch = false; let isMatch = false;
if (pattern instanceof RegExp) { if (regex) {
isMatch = pattern.test(item); isMatch = regex.test(item);
} else { } else {
isMatch = item === pattern; isMatch = item === pattern;
// On Windows, also check for .exe extension if the pattern doesn't have it // On Windows, also check for .exe extension if the pattern doesn't have it
+27
View File
@@ -0,0 +1,27 @@
import * as path from 'path';
import { spawnSync } from 'child_process';
export function installSystemPackage(downloadPath: string): void {
const fileName = path.basename(downloadPath).toLowerCase();
const command: { binary: string; args: string[] } | undefined = fileName.endsWith('.deb')
? { binary: 'dpkg', args: ['-i', downloadPath] }
: fileName.endsWith('.pkg')
? { binary: 'installer', args: ['-pkg', downloadPath, '-target', '/'] }
: fileName.endsWith('.rpm')
? { binary: 'rpm', args: ['-i', downloadPath] }
: undefined;
if (!command) {
throw new Error(`Unsupported package type: ${fileName}`);
}
const isRoot = process.getuid && process.getuid() === 0;
const commandToRun = isRoot ? command.binary : 'sudo';
const argsToRun = isRoot ? command.args : [command.binary, ...command.args];
const result = spawnSync(commandToRun, argsToRun, { stdio: 'inherit' });
if (result.status !== 0) {
throw new Error(`Failed to install package using ${commandToRun} ${argsToRun.join(' ')}.`);
}
}
+82 -60
View File
@@ -1,67 +1,89 @@
import { PlatformInfo } from './platform'; import { PlatformInfo } from './platform';
import { minimatch } from 'minimatch';
export interface MatchOptions { type ReleaseAsset = { name: string; browser_download_url: string };
fileName?: string;
fileType?: string; const knownFileTypes: Record<string, string> = {
archive: '*.{zip,tar.gz,tgz}',
package: '*.{deb,pkg,rpm}',
linux: '*.{deb,rpm}',
macos: '*.pkg',
targz: '*.{tgz,tar.gz}',
};
function debugAssetList(label: string, assets: ReleaseAsset[]): void {
console.debug(label);
for (const asset of assets) {
console.debug(`- ${asset.name}`);
}
} }
export function getMatchingAsset(assets: any[], platform: PlatformInfo, options: MatchOptions): any { function filterByRegex(assets: ReleaseAsset[], pattern: string, dryRun?: boolean): ReleaseAsset[] {
const { fileName, fileType = 'archive' } = options;
let extPattern: string;
if (fileType === 'archive') {
extPattern = '\\.(zip|tar\\.gz|tar|tgz|7z)';
} else if (fileType === 'package') {
extPattern = '\\.(deb|rpm|pkg)';
} else {
extPattern = fileType;
}
if (!fileName) {
// Rule 1: Default matching rule
const pattern = `${platform.systemPattern}[_-]${platform.archPattern}.*${extPattern}$`;
const regex = new RegExp(pattern, 'i'); const regex = new RegExp(pattern, 'i');
const matchingAssets = assets.filter((a: any) => regex.test(a.name)); const filtered = assets.filter((asset) => regex.test(asset.name));
if (matchingAssets.length === 0) { if (dryRun) {
throw new Error(`No assets matched the default criteria: ${pattern}`); console.debug(`Filtering assets with regex: ${pattern}`);
} debugAssetList('Assets:', assets);
if (matchingAssets.length > 1) { debugAssetList('Matched assets:', filtered);
throw new Error(`Multiple assets matched the default criteria: ${matchingAssets.map((a: any) => a.name).join(', ')}`);
}
return matchingAssets[0];
} else if (fileName.startsWith('~')) {
// Rule 3: Regex matching rule
let pattern = fileName.substring(1);
const hasSystem = pattern.includes('{{SYSTEM}}');
const hasArch = pattern.includes('{{ARCH}}');
const hasExt = pattern.includes('{{EXT_PATTERN}}');
const hasEnd = pattern.endsWith('$');
if (!hasSystem && !hasArch && !hasExt && !hasEnd) {
pattern += `.*{{SYSTEM}}[_-]{{ARCH}}.*{{EXT_PATTERN}}$`;
} else if (hasSystem && hasArch && !hasExt && !hasEnd) {
pattern += `.*{{EXT_PATTERN}}$`;
}
const finalPattern = pattern
.replace(/{{SYSTEM}}/g, platform.systemPattern)
.replace(/{{ARCH}}/g, platform.archPattern)
.replace(/{{EXT_PATTERN}}/g, extPattern);
const regex = new RegExp(finalPattern, 'i');
const matchingAssets = assets.filter((a: any) => regex.test(a.name));
if (matchingAssets.length === 0) {
throw new Error(`No assets matched the regex: ${finalPattern}`);
}
if (matchingAssets.length > 1) {
throw new Error(`Multiple assets matched the criteria: ${matchingAssets.map((a: any) => a.name).join(', ')}`);
}
return matchingAssets[0];
} else {
// Rule 2: Literal matching rule
const asset = assets.find((a: any) => a.name === fileName);
if (!asset) {
throw new Error(`No asset found matching the exact name: ${fileName}`);
}
return asset;
} }
return filtered;
}
function replacePlatformPlaceholders(pattern: string, platform: PlatformInfo): string {
return pattern
.replace(/{{SYSTEM}}/g, platform.systemPattern)
.replace(/{{ARCH}}/g, platform.archPattern);
}
export function getMatchingAsset(assets: ReleaseAsset[], platform: PlatformInfo, fileName?: string, fileType?: string, dryRun?: boolean): ReleaseAsset {
// Filename provided as literal string (no ~): exact match.
if (fileName && !fileName.startsWith('~')) {
const exactMatches = assets.filter((asset) => asset.name === fileName);
if (exactMatches.length !== 1) {
throw new Error(`Expected exactly one asset to match the provided filename, matched: ${exactMatches.length}`);
}
return exactMatches[0];
}
// Filetype filtering stage (or passthrough when not provided).
let fileTypeFilteredAssets: ReleaseAsset[] = assets;
if (fileType) {
if (Object.hasOwn(knownFileTypes, fileType)) {
// 2. Known fileType key: use predefined glob.
const fileTypeGlob = knownFileTypes[fileType];
fileTypeFilteredAssets = assets.filter((asset) => minimatch(asset.name, fileTypeGlob, { nocase: true }));
} else if (fileType.startsWith('~')) {
// 3. Custom regex fileType: match regex at end of string.
const fileTypeRegex = `${fileType.substring(1)}$`;
fileTypeFilteredAssets = filterByRegex(assets, fileTypeRegex, dryRun);
} else {
// 4. Custom extension fileType: treat as plain extension glob.
const extension = fileType.replace(/^\./, '');
const fileTypeGlob = `*.${extension}`;
fileTypeFilteredAssets = assets.filter((asset) => minimatch(asset.name, fileTypeGlob, { nocase: true }));
}
}
// 4. Filename provided with ~: platform placeholder expansion and regex filtering.
if (fileName && fileName.startsWith('~')) {
const fileNamePattern = replacePlatformPlaceholders(fileName.substring(1), platform);
const fileNameFilteredAssets = filterByRegex(fileTypeFilteredAssets, fileNamePattern, dryRun);
if (fileNameFilteredAssets.length !== 1) {
throw new Error(`Expected exactly one asset to match the filename regex, matched: ${fileNameFilteredAssets.length}`);
}
return fileNameFilteredAssets[0];
}
// 5. No filename: use default {{SYSTEM}}-{{ARCH}} regex.
const defaultPattern = replacePlatformPlaceholders('{{SYSTEM}}[_-]{{ARCH}}', platform);
const defaultFilteredAssets = filterByRegex(fileTypeFilteredAssets, defaultPattern, dryRun);
// 6. Zero or multiple matches are errors.
if (defaultFilteredAssets.length !== 1) {
const errorMessage = defaultFilteredAssets.length === 0
? `No assets matched the default criteria: ${defaultPattern}`
: `Multiple assets matched the default criteria: ${defaultFilteredAssets.map((asset) => asset.name).join(', ')}`;
throw new Error(errorMessage);
}
return defaultFilteredAssets[0];
} }
+10 -5
View File
@@ -7,6 +7,11 @@ export interface PlatformInfo {
archPattern: string; archPattern: string;
} }
export interface PlatformOverrides {
system?: string;
arch?: string;
}
export const systemPatterns: Record<string, string> = { export const systemPatterns: Record<string, string> = {
linux: 'linux', linux: 'linux',
darwin: '(darwin|macos|mac|osx)', darwin: '(darwin|macos|mac|osx)',
@@ -14,13 +19,13 @@ export const systemPatterns: Record<string, string> = {
}; };
export const archPatterns: Record<string, string> = { export const archPatterns: Record<string, string> = {
x64: '(x86_64|x64|amd64)', x64: '(x86_64|x64|amd64|universal)',
arm64: '(aarch64|arm64)' arm64: '(aarch64|arm64|universal)'
}; };
export function getPlatformInfo(): PlatformInfo { export function getPlatformInfo(overrides?: PlatformOverrides): PlatformInfo {
const system = os.platform(); const system = (overrides?.system || os.platform()).toLowerCase();
const arch = os.arch(); const arch = (overrides?.arch || os.arch()).toLowerCase();
return { return {
system, system,
+50 -10
View File
@@ -1,19 +1,50 @@
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as tc from '@actions/tool-cache'; import * as tc from '@actions/tool-cache';
import * as path from 'path'; import * as path from 'path';
import * as os from 'os';
import * as fs from 'fs'; import * as fs from 'fs';
import { spawnSync } from 'child_process';
import { getPlatformInfo } from './core/platform'; import { getPlatformInfo } from './core/platform';
import { getMatchingAsset } from './core/matcher'; import { getMatchingAsset } from './core/matcher';
import { findBinary } from './core/finder'; import { findBinary } from './core/finder';
import { fetchLatestRelease } from './core/downloader'; import { fetchLatestRelease } from './core/downloader';
import { installSystemPackage } from './core/installer';
function findInstalledBinary(binaryName: string): string | undefined {
if (!binaryName.startsWith('~')) {
binaryName = `~^${binaryName}$`;
}
const dirs = [
'/usr/local/bin',
'/usr/local/sbin',
'/usr/bin',
'/usr/sbin',
'/bin',
'/sbin',
path.join(process.env.HOME || '/', 'bin'),
'/opt/homebrew/bin'
];
for (const d of dirs) {
if (!fs.existsSync(d)) {
continue;
}
const p = findBinary(d, binaryName, false, () => undefined);
if (p) {
return p;
}
}
return undefined;
}
async function run() { async function run() {
try { try {
const repository = core.getInput('repository', { required: true }); const repository = core.getInput('repository', { required: true });
const fileNameInput = core.getInput('file-name'); const fileNameInput = core.getInput('file-name');
const binaryInput = core.getInput('binary-name'); const binaryInput = core.getInput('binary-name');
const fileType = core.getInput('file-type') || 'archive'; const fileType = core.getInput('file-type');
const updateCache = core.getInput('update-cache') || 'false'; const updateCache = core.getInput('update-cache') || 'false';
const debug = core.getBooleanInput('debug'); const debug = core.getBooleanInput('debug');
const token = core.getInput('token') || process.env.GITHUB_TOKEN; const token = core.getInput('token') || process.env.GITHUB_TOKEN;
@@ -39,10 +70,7 @@ async function run() {
core.info(`Fetching latest release information for ${repository}...`); core.info(`Fetching latest release information for ${repository}...`);
const release = await fetchLatestRelease(repository, token); const release = await fetchLatestRelease(repository, token);
const asset = getMatchingAsset(release.assets, platformInfo, { const asset = getMatchingAsset(release.assets, platformInfo, fileNameInput, fileType);
fileName: fileNameInput,
fileType: fileType
});
core.info(`Selected asset: ${asset.name}`); core.info(`Selected asset: ${asset.name}`);
@@ -67,6 +95,21 @@ async function run() {
const nameLower = asset.name.toLowerCase(); const nameLower = asset.name.toLowerCase();
let toolDir: string; let toolDir: string;
if (/\.(deb|pkg|rpm)$/i.test(nameLower)) {
core.info(`Installing package asset ${asset.name}...`);
installSystemPackage(downloadPath);
const binaryPath = findInstalledBinary(binaryName);
if (!binaryPath) {
throw new Error(`Package installed, but binary "${binaryName}" could not be located in common executable paths.`);
}
const binaryDir = path.dirname(binaryPath);
core.addPath(binaryDir);
core.info(`Binary found at ${binaryPath}. Added ${binaryDir} to PATH.`);
return;
}
// Determine extraction method based on extension // Determine extraction method based on extension
if (/\.(tar\.gz|tar|tgz)$/i.test(nameLower)) { if (/\.(tar\.gz|tar|tgz)$/i.test(nameLower)) {
toolDir = await tc.extractTar(downloadPath); toolDir = await tc.extractTar(downloadPath);
@@ -92,16 +135,13 @@ async function run() {
} }
// Find the binary within the extracted/prepared directory // Find the binary within the extracted/prepared directory
let binaryPattern: string | RegExp;
if (binaryName.startsWith('~')) { if (binaryName.startsWith('~')) {
binaryPattern = new RegExp(binaryName.substring(1), 'i');
core.info(`Searching for binary matching regex: ${binaryName.substring(1)}`); core.info(`Searching for binary matching regex: ${binaryName.substring(1)}`);
} else { } else {
binaryPattern = binaryName;
core.info(`Searching for binary named: ${binaryName}`); core.info(`Searching for binary named: ${binaryName}`);
} }
const binaryPath = findBinary(toolDir, binaryPattern, debug, (msg) => core.info(msg)); const binaryPath = findBinary(toolDir, binaryName, debug, (msg) => core.info(msg));
if (!binaryPath) { if (!binaryPath) {
throw new Error(`Could not find binary "${binaryName}" in the extracted asset.`); throw new Error(`Could not find binary "${binaryName}" in the extracted asset.`);
} }
+1
View File
@@ -3,6 +3,7 @@
"target": "ES2022", "target": "ES2022",
"module": "commonjs", "module": "commonjs",
"outDir": "lib", "outDir": "lib",
"types": ["node"],
"esModuleInterop": true, "esModuleInterop": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"strict": true, "strict": true,