Implemented asset matching. Added a local test workflow.
Some checks failed
Test Action / test (push) Failing after 4s
Some checks failed
Test Action / test (push) Failing after 4s
This commit is contained in:
@@ -8,12 +8,18 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Test Download Hugo
|
- name: Test Download Hugo (Regex)
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
repo-name: 'gohugoio/hugo'
|
||||||
|
file-name: '~hugo_extended'
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
|
||||||
|
- name: Test Download Hugo (Default)
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
repo-name: 'gohugoio/hugo'
|
repo-name: 'gohugoio/hugo'
|
||||||
file-name: 'hugo_extended_.*_{{SYSTEM}}-{{ARCH}}\.tar\.gz'
|
|
||||||
use-regex: 'true'
|
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
|
||||||
34
README.md
34
README.md
@@ -1,13 +1,37 @@
|
|||||||
# Setup GitHub Release Action
|
# setup-github-release
|
||||||
|
|
||||||
This GitHub/Gitea Action downloads a release from a specified GitHub repository and adds it to the runners tool cache.
|
This GitHub/Gitea Action downloads a tool from a GitHub release based on platform-aware selection rules and adds it to the system PATH.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
### Simple (Automatic Selection)
|
||||||
|
The action will automatically detect your OS and ARCH and look for a matching archive.
|
||||||
```yaml
|
```yaml
|
||||||
- uses: ./
|
- uses: ./
|
||||||
with:
|
with:
|
||||||
repo-name: 'owner/repo'
|
repo-name: 'gohugoio/hugo'
|
||||||
file-name: 'tool-linux.*'
|
|
||||||
use-regex: 'true'
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Regex Search
|
||||||
|
You can use a regex pattern (prefixed with `~`) to narrow down the asset.
|
||||||
|
```yaml
|
||||||
|
- uses: ./
|
||||||
|
with:
|
||||||
|
repo-name: 'gohugoio/hugo'
|
||||||
|
file-name: '~hugo_extended'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom File Type
|
||||||
|
```yaml
|
||||||
|
- uses: ./
|
||||||
|
with:
|
||||||
|
repo-name: 'some/repo'
|
||||||
|
file-type: 'package' # Matches .deb, .rpm, .pkg
|
||||||
|
```
|
||||||
|
|
||||||
|
## Inputs
|
||||||
|
|
||||||
|
- `repo-name` (required): GitHub repository in `owner/repo` format.
|
||||||
|
- `file-name` (optional): Literal name or regex pattern (if starts with `~`) to match the asset.
|
||||||
|
- `file-type` (optional, default: `archive`): Predefined keywords `archive`, `package`, or a custom regex extension pattern.
|
||||||
|
- `token` (optional): GitHub token for authentication.
|
||||||
|
|||||||
10
action.yml
10
action.yml
@@ -1,17 +1,17 @@
|
|||||||
name: 'setup-github-release'
|
name: 'setup-github-release'
|
||||||
description: 'Install a tool from a GitHub release and add it to the PATH'
|
description: 'Install a tool from a GitHub release and add it to the PATH'
|
||||||
author: 'GitHub Copilot'
|
author: 'Slawomir Koszewski with GitHub Copilot assistance'
|
||||||
inputs:
|
inputs:
|
||||||
repo-name:
|
repo-name:
|
||||||
description: 'The GitHub repository name (e.g., owner/repo)'
|
description: 'The GitHub repository name (e.g., owner/repo)'
|
||||||
required: true
|
required: true
|
||||||
file-name:
|
file-name:
|
||||||
description: 'The name of the asset to download (or a regex pattern if use-regex is true)'
|
description: 'The name or regex pattern (prefixed with ~) of the asset file to download.'
|
||||||
required: false
|
required: false
|
||||||
use-regex:
|
file-type:
|
||||||
description: 'Whether to treat file-name as a regular expression'
|
description: 'The type of the file to be downloaded (archive, package, or custom regex).'
|
||||||
required: false
|
required: false
|
||||||
default: 'false'
|
default: 'archive'
|
||||||
token:
|
token:
|
||||||
description: 'The GitHub token to use for authentication'
|
description: 'The GitHub token to use for authentication'
|
||||||
required: false
|
required: false
|
||||||
|
|||||||
76
src/index.ts
76
src/index.ts
@@ -7,26 +7,35 @@ async function run() {
|
|||||||
try {
|
try {
|
||||||
const repoName = core.getInput('repo-name', { required: true });
|
const repoName = core.getInput('repo-name', { required: true });
|
||||||
let fileName = core.getInput('file-name');
|
let fileName = core.getInput('file-name');
|
||||||
const useRegex = core.getInput('use-regex') === 'true';
|
const fileType = core.getInput('file-type') || 'archive';
|
||||||
const token = core.getInput('token') || process.env.GITHUB_TOKEN;
|
const token = core.getInput('token') || process.env.GITHUB_TOKEN;
|
||||||
|
|
||||||
if (!fileName) {
|
// Detect system and architecture
|
||||||
throw new Error('file-name must be provided (either as a string or regex pattern)');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Platform detection
|
|
||||||
const platform = os.platform(); // 'linux', 'darwin', 'win32'
|
const platform = os.platform(); // 'linux', 'darwin', 'win32'
|
||||||
let arch = os.arch(); // 'x64', 'arm64'
|
const arch = os.arch(); // 'x64', 'arm64'
|
||||||
|
|
||||||
// Normalize OS/Arch names for common release patterns
|
const systemPatterns: Record<string, string> = {
|
||||||
const osMap: Record<string, string> = { 'win32': 'windows', 'darwin': 'darwin' };
|
linux: 'linux',
|
||||||
const archMap: Record<string, string> = { 'x64': 'amd64' };
|
darwin: '(darwin|macos|mac)',
|
||||||
|
win32: '(windows|win)'
|
||||||
|
};
|
||||||
|
|
||||||
const currentOS = osMap[platform] || platform;
|
const archPatterns: Record<string, string> = {
|
||||||
const currentArch = archMap[arch] || arch;
|
x64: '(x86_64|x64|amd64)',
|
||||||
|
arm64: '(aarch64|arm64)'
|
||||||
|
};
|
||||||
|
|
||||||
// Replace placeholders in fileName
|
const systemPattern = systemPatterns[platform] || platform;
|
||||||
fileName = fileName.replace(/{{SYSTEM}}/g, currentOS).replace(/{{ARCH}}/g, currentArch);
|
const archPattern = archPatterns[arch] || arch;
|
||||||
|
|
||||||
|
let extPattern: string;
|
||||||
|
if (fileType === 'archive') {
|
||||||
|
extPattern = '\\.(zip|tar\\.gz|tar|tgz|7z)';
|
||||||
|
} else if (fileType === 'package') {
|
||||||
|
extPattern = '\\.(deb|rpm|pkg)';
|
||||||
|
} else {
|
||||||
|
extPattern = fileType;
|
||||||
|
}
|
||||||
|
|
||||||
const url = `https://api.github.com/repos/${repoName}/releases/latest`;
|
const url = `https://api.github.com/repos/${repoName}/releases/latest`;
|
||||||
const headers: Record<string, string> = {
|
const headers: Record<string, string> = {
|
||||||
@@ -45,15 +54,46 @@ async function run() {
|
|||||||
|
|
||||||
const data: any = await response.json();
|
const data: any = await response.json();
|
||||||
let asset;
|
let asset;
|
||||||
if (useRegex) {
|
|
||||||
const regex = new RegExp(fileName);
|
if (!fileName) {
|
||||||
asset = data.assets.find((a: any) => regex.test(a.name));
|
// Default matching rule
|
||||||
|
const pattern = `${systemPattern}[_-]${archPattern}.*${extPattern}$`;
|
||||||
|
const regex = new RegExp(pattern, 'i');
|
||||||
|
core.info(`No file-name provided. Using default pattern: ${pattern}`);
|
||||||
|
const matchingAssets = data.assets.filter((a: any) => regex.test(a.name));
|
||||||
|
if (matchingAssets.length > 1) {
|
||||||
|
throw new Error(`Multiple assets matched the default criteria: ${matchingAssets.map((a: any) => a.name).join(', ')}`);
|
||||||
|
}
|
||||||
|
asset = matchingAssets[0];
|
||||||
|
} else if (fileName.startsWith('~')) {
|
||||||
|
// Regex matching rule
|
||||||
|
let pattern = fileName.substring(1);
|
||||||
|
const hasSystem = pattern.includes('{{SYSTEM}}');
|
||||||
|
const hasArch = pattern.includes('{{ARCH}}');
|
||||||
|
const hasEnd = pattern.endsWith('$');
|
||||||
|
|
||||||
|
if (!hasSystem && !hasArch && !hasEnd) {
|
||||||
|
pattern += `.*${systemPattern}[_-]${archPattern}.*${extPattern}$`;
|
||||||
|
} else if (hasSystem && hasArch && !hasEnd) {
|
||||||
|
pattern += `.*${extPattern}$`;
|
||||||
|
}
|
||||||
|
|
||||||
|
pattern = pattern.replace(/{{SYSTEM}}/g, systemPattern).replace(/{{ARCH}}/g, archPattern);
|
||||||
|
const regex = new RegExp(pattern, 'i');
|
||||||
|
core.info(`Using regex pattern: ${pattern}`);
|
||||||
|
const matchingAssets = data.assets.filter((a: any) => regex.test(a.name));
|
||||||
|
if (matchingAssets.length > 1) {
|
||||||
|
throw new Error(`Multiple assets matched the criteria: ${matchingAssets.map((a: any) => a.name).join(', ')}`);
|
||||||
|
}
|
||||||
|
asset = matchingAssets[0];
|
||||||
} else {
|
} else {
|
||||||
|
// Literal matching rule
|
||||||
|
core.info(`Using literal match for: ${fileName}`);
|
||||||
asset = data.assets.find((a: any) => a.name === fileName);
|
asset = data.assets.find((a: any) => a.name === fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!asset) {
|
if (!asset) {
|
||||||
throw new Error(`Asset matching "${fileName}" not found in release ${data.tag_name}`);
|
throw new Error(`No asset found matching the criteria in release ${data.tag_name}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const downloadUrl = asset.browser_download_url;
|
const downloadUrl = asset.browser_download_url;
|
||||||
|
|||||||
Reference in New Issue
Block a user