feat!: set asset label to real file name (#1189)

This commit is contained in:
Fabian-Lars
2025-11-16 17:05:49 +01:00
committed by GitHub
parent 1898cf45ee
commit 5d35c8e318
6 changed files with 72 additions and 45 deletions

View File

@@ -0,0 +1,5 @@
---
action: major
---
The upload release assets will now have the original file as its `label` which will show as the filename on the GitHub Release page and will be used internally to update assets on reruns and to get the download urls for latest.json

View File

@@ -81,14 +81,14 @@ jobs:
These inputs allow you to change how your Tauri project will be build.
| Name | Required | Description | Type | Default |
| ----------------------- | :------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------ | ------------------------------------------------------------------------------ |
| `projectPath` | false | The path to the root of the tauri project relative to the current working directory | string | . |
| `includeUpdaterJson` | false | whether to upload a JSON file for the updater or not (only relevant if the updater is configured) | bool | true |
| `updaterJsonPreferNsis` | false | whether the action will use the NSIS (setup.exe) or WiX (.msi) bundles for the updater JSON if both types exist | bool | `false`. May be changed to `true` for projects using `tauri@v2` in the future. |
| `tauriScript` | false | the script to execute the Tauri CLI. It must not include any args or commands like `build` | string | `npm run\|pnpm\|yarn tauri` |
| `args` | false | Additional arguments to the current build command | string | |
| `retryAttempts` | false | The number of times to re-try building the app if the initial build fails. For now this only affects `tauri build` but may include the upload steps in the future. | number | 0 |
| Name | Required | Description | Type | Default |
| ----------------------- | :------: | ------------------------------------------------------------------------------------------------------------------ | ------ | ------------------------------------------------------------------------------ |
| `projectPath` | false | The path to the root of the tauri project relative to the current working directory | string | . |
| `includeUpdaterJson` | false | whether to upload a JSON file for the updater or not (only relevant if the updater is configured) | bool | true |
| `updaterJsonPreferNsis` | false | whether the action will use the NSIS (setup.exe) or WiX (.msi) bundles for the updater JSON if both types exist | bool | `false`. May be changed to `true` for projects using `tauri@v2` in the future. |
| `tauriScript` | false | the script to execute the Tauri CLI. It must not include any args or commands like `build` | string | `npm run\|pnpm\|yarn tauri` |
| `args` | false | Additional arguments to the current build command | string | |
| `retryAttempts` | false | The number of times to re-try building the app if the initial build fails or uploading assets if the upload fails. | number | 0 |
### Release Configuration

6
dist/index.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -2,7 +2,12 @@ import fs from 'node:fs';
import { getOctokit } from '@actions/github';
import { deleteGiteaReleaseAsset, getAssetName, retry } from './utils';
import {
deleteGiteaReleaseAsset,
getAssetName,
ghAssetName,
retry,
} from './utils';
import type { Artifact } from './types';
export async function uploadAssets(
@@ -47,16 +52,10 @@ export async function uploadAssets(
};
const assetName = getAssetName(asset, releaseAssetNamePattern);
const assetNameGH = ghAssetName(asset, releaseAssetNamePattern);
const existingAsset = existingAssets.find(
(a) =>
a.name ===
assetName
.trim()
.replace(/[ ()[\]{}]/g, '.')
.replace(/\.\./g, '.')
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, ''),
(a) => a.label === assetName || a.name === assetNameGH,
);
if (existingAsset) {
@@ -85,6 +84,8 @@ export async function uploadAssets(
github.rest.repos.uploadReleaseAsset({
headers,
name: assetName,
// GitHub renames the filename so we'll also set the label which it leaves as-is.
label: assetName,
// https://github.com/tauri-apps/tauri-action/pull/45
// @ts-expect-error error TS2322: Type 'Buffer' is not assignable to type 'string'.
data: fs.createReadStream(asset.path),
@@ -94,5 +95,7 @@ export async function uploadAssets(
}),
retryAttempts + 1,
);
console.log(`${assetName} successfully uploaded.`);
}
}

View File

@@ -4,7 +4,7 @@ import { basename, extname, resolve } from 'node:path';
import { getOctokit } from '@actions/github';
import { uploadAssets } from './upload-release-assets';
import { deleteGiteaReleaseAsset, getAssetName } from './utils';
import { deleteGiteaReleaseAsset, getAssetName, ghAssetName } from './utils';
import type { Artifact, TargetInfo } from './types';
import { createArtifact } from './utils';
@@ -23,18 +23,6 @@ type VersionContent = {
};
};
function ghAssetName(
artifact: Artifact,
releaseAssetNamePattern?: string,
): string {
return getAssetName(artifact, releaseAssetNamePattern)
.trim()
.replace(/[ ()[\]{}]/g, '.')
.replace(/\.\./g, '.')
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '');
}
export async function uploadVersionJSON(
owner: string,
repo: string,
@@ -122,9 +110,17 @@ export async function uploadVersionJSON(
}
}
const downloadUrls = new Map<string, string>();
const downloadUrls: {
name: string;
label: string | null;
url: string;
}[] = [];
for (const data of assets.data) {
downloadUrls.set(data.name, data.browser_download_url);
downloadUrls.push({
name: data.name,
label: data.label,
url: data.browser_download_url,
});
}
// Assets matching artifacts generated by this action
@@ -134,23 +130,31 @@ export async function uploadVersionJSON(
let hasNativeX64;
for (const artifact of artifacts) {
if (artifact.ext === '.app.tar.gz' && artifact.arch === 'universal') {
const arm = ghAssetName(
{ ...artifact, arch: 'aarch64' },
releaseAssetNamePattern,
const arm = { ...artifact, arch: 'aarch64' };
const x64 = { ...artifact, arch: 'x86_64' };
const armName = ghAssetName(arm, releaseAssetNamePattern);
const armLabel = getAssetName(arm, releaseAssetNamePattern);
const x64Name = ghAssetName(x64, releaseAssetNamePattern);
const x64Label = getAssetName(x64, releaseAssetNamePattern);
hasNativeArm = !!downloadUrls.find(
(a) => a.label === armLabel || a.name === armName,
);
const x86 = ghAssetName(
{ ...artifact, arch: 'x86_64' },
releaseAssetNamePattern,
hasNativeX64 = !!downloadUrls.find(
(a) => a.label === x64Label || a.name === x64Name,
);
hasNativeArm = downloadUrls.has(arm);
hasNativeX64 = downloadUrls.has(x86);
}
const assetLabel = getAssetName(artifact, releaseAssetNamePattern);
const assetName = ghAssetName(artifact, releaseAssetNamePattern);
const downloadUrl = downloadUrls.get(assetName);
const downloadUrl = downloadUrls.find(
(a) => a.label === assetLabel || a.name === assetName,
)?.url;
if (downloadUrl) {
filteredAssets.push({
downloadUrl,
assetLabel,
assetName,
path: artifact.path,
arch: artifact.arch,
@@ -195,12 +199,17 @@ export async function uploadVersionJSON(
}
for (const [idx, signatureFile] of signatureFiles.entries()) {
const updaterFileLabel = basename(
signatureFile.assetLabel,
extname(signatureFile.assetLabel),
);
const updaterFileName = basename(
signatureFile.assetName,
extname(signatureFile.assetName),
);
let updaterFileDownloadUrl = filteredAssets.find(
(asset) => asset.assetName === updaterFileName,
(a) =>
a.assetLabel === updaterFileLabel || a.assetName === updaterFileName,
)?.downloadUrl;
if (!updaterFileDownloadUrl) {

View File

@@ -595,4 +595,14 @@ export function deleteGiteaReleaseAsset(
);
}
export function ghAssetName(
artifact: Artifact,
releaseAssetNamePattern?: string,
) {
return getAssetName(artifact, releaseAssetNamePattern)
.trim()
.replace(/[^a-zA-Z0-9_-]/g, '.')
.replace(/\.\./g, '.');
}
// TODO: Properly resolve the eslint issues in this file.