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
+5
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
+2 -2
View File
@@ -82,13 +82,13 @@ jobs:
These inputs allow you to change how your Tauri project will be build. These inputs allow you to change how your Tauri project will be build.
| Name | Required | Description | Type | Default | | Name | Required | Description | Type | Default |
| ----------------------- | :------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------ | ------------------------------------------------------------------------------ | | ----------------------- | :------: | ------------------------------------------------------------------------------------------------------------------ | ------ | ------------------------------------------------------------------------------ |
| `projectPath` | false | The path to the root of the tauri project relative to the current working directory | string | . | | `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 | | `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. | | `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` | | `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 | | | `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 | | `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 ### Release Configuration
+3 -3
View File
File diff suppressed because one or more lines are too long
+12 -9
View File
@@ -2,7 +2,12 @@ import fs from 'node:fs';
import { getOctokit } from '@actions/github'; import { getOctokit } from '@actions/github';
import { deleteGiteaReleaseAsset, getAssetName, retry } from './utils'; import {
deleteGiteaReleaseAsset,
getAssetName,
ghAssetName,
retry,
} from './utils';
import type { Artifact } from './types'; import type { Artifact } from './types';
export async function uploadAssets( export async function uploadAssets(
@@ -47,16 +52,10 @@ export async function uploadAssets(
}; };
const assetName = getAssetName(asset, releaseAssetNamePattern); const assetName = getAssetName(asset, releaseAssetNamePattern);
const assetNameGH = ghAssetName(asset, releaseAssetNamePattern);
const existingAsset = existingAssets.find( const existingAsset = existingAssets.find(
(a) => (a) => a.label === assetName || a.name === assetNameGH,
a.name ===
assetName
.trim()
.replace(/[ ()[\]{}]/g, '.')
.replace(/\.\./g, '.')
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, ''),
); );
if (existingAsset) { if (existingAsset) {
@@ -85,6 +84,8 @@ export async function uploadAssets(
github.rest.repos.uploadReleaseAsset({ github.rest.repos.uploadReleaseAsset({
headers, headers,
name: assetName, 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 // https://github.com/tauri-apps/tauri-action/pull/45
// @ts-expect-error error TS2322: Type 'Buffer' is not assignable to type 'string'. // @ts-expect-error error TS2322: Type 'Buffer' is not assignable to type 'string'.
data: fs.createReadStream(asset.path), data: fs.createReadStream(asset.path),
@@ -94,5 +95,7 @@ export async function uploadAssets(
}), }),
retryAttempts + 1, retryAttempts + 1,
); );
console.log(`${assetName} successfully uploaded.`);
} }
} }
+34 -25
View File
@@ -4,7 +4,7 @@ import { basename, extname, resolve } from 'node:path';
import { getOctokit } from '@actions/github'; import { getOctokit } from '@actions/github';
import { uploadAssets } from './upload-release-assets'; import { uploadAssets } from './upload-release-assets';
import { deleteGiteaReleaseAsset, getAssetName } from './utils'; import { deleteGiteaReleaseAsset, getAssetName, ghAssetName } from './utils';
import type { Artifact, TargetInfo } from './types'; import type { Artifact, TargetInfo } from './types';
import { createArtifact } from './utils'; 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( export async function uploadVersionJSON(
owner: string, owner: string,
repo: 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) { 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 // Assets matching artifacts generated by this action
@@ -134,23 +130,31 @@ export async function uploadVersionJSON(
let hasNativeX64; let hasNativeX64;
for (const artifact of artifacts) { for (const artifact of artifacts) {
if (artifact.ext === '.app.tar.gz' && artifact.arch === 'universal') { if (artifact.ext === '.app.tar.gz' && artifact.arch === 'universal') {
const arm = ghAssetName( const arm = { ...artifact, arch: 'aarch64' };
{ ...artifact, arch: 'aarch64' }, const x64 = { ...artifact, arch: 'x86_64' };
releaseAssetNamePattern,
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( hasNativeX64 = !!downloadUrls.find(
{ ...artifact, arch: 'x86_64' }, (a) => a.label === x64Label || a.name === x64Name,
releaseAssetNamePattern,
); );
hasNativeArm = downloadUrls.has(arm);
hasNativeX64 = downloadUrls.has(x86);
} }
const assetLabel = getAssetName(artifact, releaseAssetNamePattern);
const assetName = ghAssetName(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) { if (downloadUrl) {
filteredAssets.push({ filteredAssets.push({
downloadUrl, downloadUrl,
assetLabel,
assetName, assetName,
path: artifact.path, path: artifact.path,
arch: artifact.arch, arch: artifact.arch,
@@ -195,12 +199,17 @@ export async function uploadVersionJSON(
} }
for (const [idx, signatureFile] of signatureFiles.entries()) { for (const [idx, signatureFile] of signatureFiles.entries()) {
const updaterFileLabel = basename(
signatureFile.assetLabel,
extname(signatureFile.assetLabel),
);
const updaterFileName = basename( const updaterFileName = basename(
signatureFile.assetName, signatureFile.assetName,
extname(signatureFile.assetName), extname(signatureFile.assetName),
); );
let updaterFileDownloadUrl = filteredAssets.find( let updaterFileDownloadUrl = filteredAssets.find(
(asset) => asset.assetName === updaterFileName, (a) =>
a.assetLabel === updaterFileLabel || a.assetName === updaterFileName,
)?.downloadUrl; )?.downloadUrl;
if (!updaterFileDownloadUrl) { if (!updaterFileDownloadUrl) {
+10
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. // TODO: Properly resolve the eslint issues in this file.