mirror of
https://github.com/tauri-apps/tauri-action.git
synced 2026-01-31 00:35:20 +01:00
refactor: evaluate action inputs in separate file (#1200)
This commit is contained in:
@@ -29,6 +29,7 @@ inputs:
|
|||||||
default: 'true'
|
default: 'true'
|
||||||
updaterJsonPreferNsis:
|
updaterJsonPreferNsis:
|
||||||
description: 'Whether the action will use the NSIS (setup.exe) or WiX (.msi) bundles for the updater JSON if both types exist. Will default to false. May default to true for apps using tauri@v2 in the future.'
|
description: 'Whether the action will use the NSIS (setup.exe) or WiX (.msi) bundles for the updater JSON if both types exist. Will default to false. May default to true for apps using tauri@v2 in the future.'
|
||||||
|
default: 'false'
|
||||||
tauriScript:
|
tauriScript:
|
||||||
description: 'The script to run to build the Tauri app'
|
description: 'The script to run to build the Tauri app'
|
||||||
args:
|
args:
|
||||||
|
|||||||
148014
dist/index.js
vendored
148014
dist/index.js
vendored
File diff suppressed because one or more lines are too long
@@ -65,7 +65,6 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
|
||||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "ncc build src/index.ts -o dist -m",
|
"build": "ncc build src/index.ts -o dist",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"format": "prettier --write src/** action.yml README.md",
|
"format": "prettier --write src/** action.yml README.md",
|
||||||
"format:check": "prettier --check src/** action.yml README.md"
|
"format:check": "prettier --check src/** action.yml README.md"
|
||||||
|
|||||||
33
src/build.ts
33
src/build.ts
@@ -2,6 +2,14 @@ import { existsSync } from 'node:fs';
|
|||||||
import { join } from 'node:path';
|
import { join } from 'node:path';
|
||||||
|
|
||||||
import { getRunner } from './runner';
|
import { getRunner } from './runner';
|
||||||
|
import {
|
||||||
|
parsedArgs,
|
||||||
|
parsedRunnerArgs,
|
||||||
|
projectPath,
|
||||||
|
rawArgs,
|
||||||
|
retryAttempts,
|
||||||
|
uploadPlainBinary,
|
||||||
|
} from './inputs';
|
||||||
import {
|
import {
|
||||||
createArtifact,
|
createArtifact,
|
||||||
getInfo,
|
getInfo,
|
||||||
@@ -10,24 +18,19 @@ import {
|
|||||||
getWorkspaceDir,
|
getWorkspaceDir,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
|
||||||
import type { Artifact, BuildOptions } from './types';
|
import type { Artifact } from './types';
|
||||||
|
|
||||||
export async function buildProject(
|
export async function buildProject(): Promise<Artifact[]> {
|
||||||
root: string,
|
const runner = await getRunner();
|
||||||
buildOpts: BuildOptions,
|
|
||||||
retryAttempts: number,
|
|
||||||
uploadPlainBinary: boolean,
|
|
||||||
): Promise<Artifact[]> {
|
|
||||||
const runner = await getRunner(root, buildOpts.tauriScript);
|
|
||||||
|
|
||||||
const debug = buildOpts.parsedArgs['debug'] as boolean;
|
const debug = parsedArgs['debug'] as boolean;
|
||||||
const targetPath = buildOpts.parsedArgs['target'] as string | undefined;
|
const targetPath = parsedArgs['target'] as string | undefined;
|
||||||
const configArg = buildOpts.parsedArgs['config'] as string | undefined;
|
const configArg = parsedArgs['config'] as string | undefined;
|
||||||
const profile = buildOpts.parsedRunnerArgs['profile'] as string | undefined;
|
const profile = parsedRunnerArgs['profile'] as string | undefined;
|
||||||
|
|
||||||
const targetInfo = getTargetInfo(targetPath);
|
const targetInfo = getTargetInfo(targetPath);
|
||||||
|
|
||||||
const info = getInfo(root, targetInfo, configArg);
|
const info = getInfo(targetInfo, configArg);
|
||||||
|
|
||||||
if (!info.tauriPath) {
|
if (!info.tauriPath) {
|
||||||
throw Error("Couldn't detect path of tauri app");
|
throw Error("Couldn't detect path of tauri app");
|
||||||
@@ -45,8 +48,8 @@ export async function buildProject(
|
|||||||
|
|
||||||
await runner.execTauriCommand(
|
await runner.execTauriCommand(
|
||||||
['build'],
|
['build'],
|
||||||
buildOpts.rawArgs || [],
|
rawArgs,
|
||||||
root,
|
projectPath,
|
||||||
targetInfo.platform === 'macos'
|
targetInfo.platform === 'macos'
|
||||||
? {
|
? {
|
||||||
TAURI_BUNDLER_DMG_IGNORE_CI:
|
TAURI_BUNDLER_DMG_IGNORE_CI:
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
|
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import { getOctokit, context } from '@actions/github';
|
import { getOctokit } from '@actions/github';
|
||||||
import type { GitHub } from '@actions/github/lib/utils';
|
import type { GitHub } from '@actions/github/lib/utils';
|
||||||
|
|
||||||
|
import {
|
||||||
|
commitish,
|
||||||
|
draft,
|
||||||
|
generateReleaseNotes,
|
||||||
|
githubBaseUrl,
|
||||||
|
owner,
|
||||||
|
prerelease,
|
||||||
|
repo,
|
||||||
|
} from './inputs';
|
||||||
|
|
||||||
interface Release {
|
interface Release {
|
||||||
id: number;
|
id: number;
|
||||||
uploadUrl: string;
|
uploadUrl: string;
|
||||||
@@ -20,8 +30,6 @@ interface GitHubRelease {
|
|||||||
|
|
||||||
function allReleases(
|
function allReleases(
|
||||||
github: InstanceType<typeof GitHub>,
|
github: InstanceType<typeof GitHub>,
|
||||||
owner: string,
|
|
||||||
repo: string,
|
|
||||||
): AsyncIterableIterator<{ data: GitHubRelease[] }> {
|
): AsyncIterableIterator<{ data: GitHubRelease[] }> {
|
||||||
const params = { per_page: 100, owner, repo };
|
const params = { per_page: 100, owner, repo };
|
||||||
return github.paginate.iterator(
|
return github.paginate.iterator(
|
||||||
@@ -31,16 +39,9 @@ function allReleases(
|
|||||||
|
|
||||||
/// Try to get release by tag. If there's none, releaseName is required to create one.
|
/// Try to get release by tag. If there's none, releaseName is required to create one.
|
||||||
export async function getOrCreateRelease(
|
export async function getOrCreateRelease(
|
||||||
owner: string,
|
|
||||||
repo: string,
|
|
||||||
tagName: string,
|
tagName: string,
|
||||||
githubBaseUrl: string,
|
|
||||||
releaseName?: string,
|
releaseName?: string,
|
||||||
body?: string,
|
body?: string,
|
||||||
commitish?: string,
|
|
||||||
draft = true,
|
|
||||||
prerelease = true,
|
|
||||||
generateReleaseNotes = false,
|
|
||||||
): Promise<Release> {
|
): Promise<Release> {
|
||||||
if (process.env.GITHUB_TOKEN === undefined) {
|
if (process.env.GITHUB_TOKEN === undefined) {
|
||||||
throw new Error('GITHUB_TOKEN is required');
|
throw new Error('GITHUB_TOKEN is required');
|
||||||
@@ -69,7 +70,7 @@ export async function getOrCreateRelease(
|
|||||||
// so we must find one in the list of all releases
|
// so we must find one in the list of all releases
|
||||||
if (draft) {
|
if (draft) {
|
||||||
console.log(`Looking for a draft release with tag ${tagName}...`);
|
console.log(`Looking for a draft release with tag ${tagName}...`);
|
||||||
for await (const response of allReleases(github, owner, repo)) {
|
for await (const response of allReleases(github)) {
|
||||||
const releaseWithTag = response.data.find(
|
const releaseWithTag = response.data.find(
|
||||||
(release) => release.tag_name === tagName,
|
(release) => release.tag_name === tagName,
|
||||||
);
|
);
|
||||||
@@ -115,7 +116,7 @@ export async function getOrCreateRelease(
|
|||||||
body: bodyFileContent || body,
|
body: bodyFileContent || body,
|
||||||
draft,
|
draft,
|
||||||
prerelease,
|
prerelease,
|
||||||
target_commitish: commitish || context.sha,
|
target_commitish: commitish,
|
||||||
generate_release_notes: generateReleaseNotes,
|
generate_release_notes: generateReleaseNotes,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
126
src/index.ts
126
src/index.ts
@@ -1,101 +1,37 @@
|
|||||||
import { existsSync } from 'node:fs';
|
import { existsSync } from 'node:fs';
|
||||||
import { resolve, dirname, basename } from 'node:path';
|
import { dirname, basename } from 'node:path';
|
||||||
|
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import { context } from '@actions/github';
|
|
||||||
import stringArgv from 'string-argv';
|
|
||||||
|
|
||||||
|
import { buildProject } from './build';
|
||||||
import { getOrCreateRelease } from './create-release';
|
import { getOrCreateRelease } from './create-release';
|
||||||
|
import {
|
||||||
|
includeUpdaterJson,
|
||||||
|
parsedArgs,
|
||||||
|
retryAttempts,
|
||||||
|
shouldUploadWorkflowArtifacts,
|
||||||
|
} from './inputs';
|
||||||
import { uploadAssets as uploadReleaseAssets } from './upload-release-assets';
|
import { uploadAssets as uploadReleaseAssets } from './upload-release-assets';
|
||||||
import { uploadVersionJSON } from './upload-version-json';
|
import { uploadVersionJSON } from './upload-version-json';
|
||||||
import { buildProject } from './build';
|
import { uploadWorkflowArtifacts } from './upload-workflow-artifacts';
|
||||||
import { execCommand, getInfo, getTargetInfo, retry } from './utils';
|
import { execCommand, getInfo, getTargetInfo, retry } from './utils';
|
||||||
|
|
||||||
import type { Artifact, BuildOptions } from './types';
|
import type { Artifact } from './types';
|
||||||
import { uploadWorkflowArtifacts } from './upload-workflow-artifacts';
|
|
||||||
import { parseArgs } from 'node:util';
|
|
||||||
|
|
||||||
async function run(): Promise<void> {
|
async function run(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const projectPath = resolve(
|
// inputs that won't be changed are in ./inputs
|
||||||
process.cwd(),
|
|
||||||
core.getInput('projectPath') || process.argv[2],
|
|
||||||
);
|
|
||||||
const includeUpdaterJson = core.getBooleanInput('includeUpdaterJson');
|
|
||||||
const retryAttempts = parseInt(core.getInput('retryAttempts') || '0', 10);
|
|
||||||
const tauriScript = core.getInput('tauriScript');
|
|
||||||
const releaseAssetNamePattern = core.getInput('releaseAssetNamePattern');
|
|
||||||
const rawArgs = stringArgv(core.getInput('args'));
|
|
||||||
const parsedArgs = parseArgs({
|
|
||||||
args: rawArgs,
|
|
||||||
strict: false,
|
|
||||||
options: {
|
|
||||||
target: { type: 'string', short: 't' },
|
|
||||||
config: {
|
|
||||||
type: 'string',
|
|
||||||
short: 'c',
|
|
||||||
},
|
|
||||||
debug: { type: 'boolean', short: 'd' },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const parsedRunnerArgs = parseArgs({
|
|
||||||
args: parsedArgs.positionals,
|
|
||||||
strict: false,
|
|
||||||
options: { profile: { type: 'string' } },
|
|
||||||
});
|
|
||||||
|
|
||||||
const uploadPlainBinary = core.getBooleanInput('uploadPlainBinary');
|
|
||||||
|
|
||||||
let tagName = core.getInput('tagName').replace('refs/tags/', '');
|
let tagName = core.getInput('tagName').replace('refs/tags/', '');
|
||||||
let releaseId = Number(core.getInput('releaseId'));
|
let releaseId = Number(core.getInput('releaseId'));
|
||||||
let releaseName = core.getInput('releaseName').replace('refs/tags/', '');
|
let releaseName = core.getInput('releaseName').replace('refs/tags/', '');
|
||||||
let body = core.getInput('releaseBody');
|
let body = core.getInput('releaseBody');
|
||||||
const owner = core.getInput('owner') || context.repo.owner;
|
|
||||||
const repo = core.getInput('repo') || context.repo.repo;
|
|
||||||
const draft = core.getBooleanInput('releaseDraft');
|
|
||||||
const prerelease = core.getBooleanInput('prerelease');
|
|
||||||
const commitish = core.getInput('releaseCommitish') || null;
|
|
||||||
const githubBaseUrl =
|
|
||||||
core.getInput('githubBaseUrl') ||
|
|
||||||
process.env.GITHUB_API_URL ||
|
|
||||||
'https://api.github.com';
|
|
||||||
const isGitea = core.getBooleanInput('isGitea');
|
|
||||||
const generateReleaseNotes = core.getBooleanInput('generateReleaseNotes');
|
|
||||||
const shouldUploadWorkflowArtifacts = core.getBooleanInput(
|
|
||||||
'uploadWorkflowArtifacts',
|
|
||||||
);
|
|
||||||
const workflowArtifactNamePattern =
|
|
||||||
core.getInput('workflowArtifactNamePattern') ||
|
|
||||||
'[platform]-[arch]-[bundle]';
|
|
||||||
const uploadUpdaterSignatures = core.getBooleanInput(
|
|
||||||
'uploadUpdaterSignatures',
|
|
||||||
);
|
|
||||||
|
|
||||||
// TODO: Change its default to true for v2 apps
|
const targetPath = parsedArgs['target'] as string | undefined;
|
||||||
// Not using getBooleanInput so we can differentiate between true,false,unset later.
|
const configArg = parsedArgs['config'] as string | undefined;
|
||||||
const updaterJsonPreferNsis =
|
|
||||||
core.getInput('updaterJsonPreferNsis')?.toLowerCase() === 'true';
|
|
||||||
|
|
||||||
const buildOptions: BuildOptions = {
|
|
||||||
tauriScript,
|
|
||||||
rawArgs,
|
|
||||||
parsedArgs: parsedArgs.values,
|
|
||||||
parsedRunnerArgs: parsedRunnerArgs.values,
|
|
||||||
};
|
|
||||||
|
|
||||||
const targetPath = buildOptions.parsedArgs['target'] as string | undefined;
|
|
||||||
const configArg = buildOptions.parsedArgs['config'] as string | undefined;
|
|
||||||
|
|
||||||
const artifacts: Artifact[] = [];
|
const artifacts: Artifact[] = [];
|
||||||
|
|
||||||
artifacts.push(
|
artifacts.push(...(await buildProject()));
|
||||||
...(await buildProject(
|
|
||||||
projectPath,
|
|
||||||
buildOptions,
|
|
||||||
retryAttempts,
|
|
||||||
uploadPlainBinary,
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (artifacts.length === 0) {
|
if (artifacts.length === 0) {
|
||||||
if (releaseId || tagName || shouldUploadWorkflowArtifacts) {
|
if (releaseId || tagName || shouldUploadWorkflowArtifacts) {
|
||||||
@@ -115,16 +51,12 @@ async function run(): Promise<void> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const targetInfo = getTargetInfo(targetPath);
|
const targetInfo = getTargetInfo(targetPath);
|
||||||
const info = getInfo(projectPath, targetInfo, configArg);
|
const info = getInfo(targetInfo, configArg);
|
||||||
core.setOutput('appVersion', info.version);
|
core.setOutput('appVersion', info.version);
|
||||||
|
|
||||||
// Since artifacts are .zip archives we can do this before the .tar.gz step below.
|
// Since artifacts are .zip archives we can do this before the .tar.gz step below.
|
||||||
if (shouldUploadWorkflowArtifacts) {
|
if (shouldUploadWorkflowArtifacts) {
|
||||||
await uploadWorkflowArtifacts(
|
await uploadWorkflowArtifacts(artifacts);
|
||||||
artifacts,
|
|
||||||
workflowArtifactNamePattern,
|
|
||||||
retryAttempts,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Other steps may benefit from this so we do this whether or not we want to upload it.
|
// Other steps may benefit from this so we do this whether or not we want to upload it.
|
||||||
@@ -177,16 +109,9 @@ async function run(): Promise<void> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const releaseData = await getOrCreateRelease(
|
const releaseData = await getOrCreateRelease(
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
tagName,
|
tagName,
|
||||||
githubBaseUrl,
|
|
||||||
releaseName || undefined,
|
releaseName || undefined,
|
||||||
body,
|
body,
|
||||||
commitish || undefined,
|
|
||||||
draft,
|
|
||||||
prerelease,
|
|
||||||
generateReleaseNotes,
|
|
||||||
);
|
);
|
||||||
releaseId = releaseData.id;
|
releaseId = releaseData.id;
|
||||||
core.setOutput('releaseUploadUrl', releaseData.uploadUrl);
|
core.setOutput('releaseUploadUrl', releaseData.uploadUrl);
|
||||||
@@ -195,17 +120,7 @@ async function run(): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (releaseId) {
|
if (releaseId) {
|
||||||
await uploadReleaseAssets(
|
await uploadReleaseAssets(releaseId, artifacts, retryAttempts);
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
releaseId,
|
|
||||||
artifacts,
|
|
||||||
retryAttempts,
|
|
||||||
githubBaseUrl,
|
|
||||||
isGitea,
|
|
||||||
releaseAssetNamePattern,
|
|
||||||
uploadUpdaterSignatures,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (includeUpdaterJson) {
|
if (includeUpdaterJson) {
|
||||||
// Once we start throwing our own errors in this function we may need some custom retry logic.
|
// Once we start throwing our own errors in this function we may need some custom retry logic.
|
||||||
@@ -213,8 +128,6 @@ async function run(): Promise<void> {
|
|||||||
await retry(
|
await retry(
|
||||||
() =>
|
() =>
|
||||||
uploadVersionJSON(
|
uploadVersionJSON(
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
info.version,
|
info.version,
|
||||||
body,
|
body,
|
||||||
tagName,
|
tagName,
|
||||||
@@ -222,11 +135,6 @@ async function run(): Promise<void> {
|
|||||||
artifacts,
|
artifacts,
|
||||||
targetInfo,
|
targetInfo,
|
||||||
info.unzippedSigs,
|
info.unzippedSigs,
|
||||||
updaterJsonPreferNsis,
|
|
||||||
retryAttempts,
|
|
||||||
githubBaseUrl,
|
|
||||||
isGitea,
|
|
||||||
releaseAssetNamePattern,
|
|
||||||
),
|
),
|
||||||
// since all jobs try to upload this file it tends to conflict often so we want to retry it at least once.
|
// since all jobs try to upload this file it tends to conflict often so we want to retry it at least once.
|
||||||
retryAttempts === 0 ? 1 : retryAttempts,
|
retryAttempts === 0 ? 1 : retryAttempts,
|
||||||
|
|||||||
86
src/inputs.ts
Normal file
86
src/inputs.ts
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
import { resolve } from 'node:path';
|
||||||
|
import { parseArgs } from 'node:util';
|
||||||
|
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
import { context } from '@actions/github';
|
||||||
|
import stringArgv from 'string-argv';
|
||||||
|
|
||||||
|
export const projectPath = resolve(
|
||||||
|
process.cwd(),
|
||||||
|
core.getInput('projectPath') || process.argv[2],
|
||||||
|
);
|
||||||
|
|
||||||
|
export const includeUpdaterJson = core.getBooleanInput('includeUpdaterJson');
|
||||||
|
|
||||||
|
export const retryAttempts = parseInt(
|
||||||
|
core.getInput('retryAttempts') || '0',
|
||||||
|
10,
|
||||||
|
);
|
||||||
|
|
||||||
|
export const tauriScript = core.getInput('tauriScript') || undefined;
|
||||||
|
|
||||||
|
export const releaseAssetNamePattern =
|
||||||
|
core.getInput('releaseAssetNamePattern') || undefined;
|
||||||
|
|
||||||
|
export const rawArgs = stringArgv(core.getInput('args'));
|
||||||
|
|
||||||
|
const parsedArgs_ = parseArgs({
|
||||||
|
args: rawArgs,
|
||||||
|
strict: false,
|
||||||
|
options: {
|
||||||
|
target: { type: 'string', short: 't' },
|
||||||
|
config: {
|
||||||
|
type: 'string',
|
||||||
|
short: 'c',
|
||||||
|
},
|
||||||
|
debug: { type: 'boolean', short: 'd' },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const parsedRunnerArgs_ = parseArgs({
|
||||||
|
args: parsedArgs_.positionals,
|
||||||
|
strict: false,
|
||||||
|
options: { profile: { type: 'string' } },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const parsedArgs = parsedArgs_.values;
|
||||||
|
|
||||||
|
export const parsedRunnerArgs = parsedRunnerArgs_.values;
|
||||||
|
|
||||||
|
export const uploadPlainBinary = core.getBooleanInput('uploadPlainBinary');
|
||||||
|
|
||||||
|
export const owner = core.getInput('owner') || context.repo.owner;
|
||||||
|
|
||||||
|
export const repo = core.getInput('repo') || context.repo.repo;
|
||||||
|
|
||||||
|
export const draft = core.getBooleanInput('releaseDraft');
|
||||||
|
|
||||||
|
export const prerelease = core.getBooleanInput('prerelease');
|
||||||
|
|
||||||
|
export const commitish = core.getInput('releaseCommitish') || context.sha;
|
||||||
|
|
||||||
|
export const githubBaseUrl =
|
||||||
|
core.getInput('githubBaseUrl') ||
|
||||||
|
process.env.GITHUB_API_URL ||
|
||||||
|
'https://api.github.com';
|
||||||
|
|
||||||
|
export const isGitea = core.getBooleanInput('isGitea');
|
||||||
|
|
||||||
|
export const generateReleaseNotes = core.getBooleanInput(
|
||||||
|
'generateReleaseNotes',
|
||||||
|
);
|
||||||
|
|
||||||
|
export const shouldUploadWorkflowArtifacts = core.getBooleanInput(
|
||||||
|
'uploadWorkflowArtifacts',
|
||||||
|
);
|
||||||
|
|
||||||
|
export const workflowArtifactNamePattern =
|
||||||
|
core.getInput('workflowArtifactNamePattern') || '[platform]-[arch]-[bundle]';
|
||||||
|
|
||||||
|
export const uploadUpdaterSignatures = core.getBooleanInput(
|
||||||
|
'uploadUpdaterSignatures',
|
||||||
|
);
|
||||||
|
|
||||||
|
export const updaterJsonPreferNsis = core.getBooleanInput(
|
||||||
|
'updaterJsonPreferNsis',
|
||||||
|
);
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { projectPath, tauriScript } from './inputs';
|
||||||
import {
|
import {
|
||||||
execCommand,
|
execCommand,
|
||||||
hasDependency,
|
hasDependency,
|
||||||
@@ -42,10 +43,7 @@ class Runner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getRunner(
|
async function getRunner(): Promise<Runner> {
|
||||||
root: string,
|
|
||||||
tauriScript: string | null,
|
|
||||||
): Promise<Runner> {
|
|
||||||
if (tauriScript) {
|
if (tauriScript) {
|
||||||
console.log('`tauriScript` set. Skipping cli verification.');
|
console.log('`tauriScript` set. Skipping cli verification.');
|
||||||
// FIXME: This will also split file paths with spaces.
|
// FIXME: This will also split file paths with spaces.
|
||||||
@@ -53,15 +51,15 @@ async function getRunner(
|
|||||||
return new Runner(runnerCommand, runnerArgs);
|
return new Runner(runnerCommand, runnerArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasDependency('@tauri-apps/cli', root)) {
|
if (hasDependency('@tauri-apps/cli', projectPath)) {
|
||||||
// usesX also check if the runner executable exists.
|
// usesX also check if the runner executable exists.
|
||||||
if (usesYarn(root)) return new Runner('yarn', ['tauri']);
|
if (usesYarn(projectPath)) return new Runner('yarn', ['tauri']);
|
||||||
if (usesPnpm(root)) return new Runner('pnpm', ['tauri']);
|
if (usesPnpm(projectPath)) return new Runner('pnpm', ['tauri']);
|
||||||
if (usesBun(root)) return new Runner('bun', ['tauri']);
|
if (usesBun(projectPath)) return new Runner('bun', ['tauri']);
|
||||||
// npm should always be available in a GitHub runner but we'll check for it anyway.
|
// npm should always be available in a GitHub runner but we'll check for it anyway.
|
||||||
if (usesNpm(root))
|
if (usesNpm(projectPath))
|
||||||
return new Runner('npm', [
|
return new Runner('npm', [
|
||||||
hasTauriScript(root) ? 'run' : 'exec',
|
hasTauriScript(projectPath) ? 'run' : 'exec',
|
||||||
'tauri',
|
'tauri',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,18 +8,21 @@ import {
|
|||||||
ghAssetName,
|
ghAssetName,
|
||||||
retry,
|
retry,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
import {
|
||||||
|
githubBaseUrl,
|
||||||
|
isGitea,
|
||||||
|
owner,
|
||||||
|
releaseAssetNamePattern,
|
||||||
|
repo,
|
||||||
|
uploadUpdaterSignatures,
|
||||||
|
} from './inputs';
|
||||||
|
|
||||||
import type { Artifact } from './types';
|
import type { Artifact } from './types';
|
||||||
|
|
||||||
export async function uploadAssets(
|
export async function uploadAssets(
|
||||||
owner: string,
|
|
||||||
repo: string,
|
|
||||||
releaseId: number,
|
releaseId: number,
|
||||||
assets: Artifact[],
|
assets: Artifact[],
|
||||||
retryAttempts: number,
|
retryAttempts: number,
|
||||||
githubBaseUrl: string,
|
|
||||||
isGitea: boolean,
|
|
||||||
releaseAssetNamePattern?: string,
|
|
||||||
uploadUpdaterSignatures?: boolean,
|
|
||||||
) {
|
) {
|
||||||
if (process.env.GITHUB_TOKEN === undefined) {
|
if (process.env.GITHUB_TOKEN === undefined) {
|
||||||
throw new Error('GITHUB_TOKEN is required');
|
throw new Error('GITHUB_TOKEN is required');
|
||||||
@@ -31,8 +34,8 @@ export async function uploadAssets(
|
|||||||
|
|
||||||
const existingAssets = (
|
const existingAssets = (
|
||||||
await github.rest.repos.listReleaseAssets({
|
await github.rest.repos.listReleaseAssets({
|
||||||
owner: owner,
|
owner,
|
||||||
repo: repo,
|
repo,
|
||||||
release_id: releaseId,
|
release_id: releaseId,
|
||||||
per_page: 100,
|
per_page: 100,
|
||||||
})
|
})
|
||||||
@@ -61,17 +64,11 @@ export async function uploadAssets(
|
|||||||
if (existingAsset) {
|
if (existingAsset) {
|
||||||
console.log(`Deleting existing ${assetName}...`);
|
console.log(`Deleting existing ${assetName}...`);
|
||||||
if (isGitea) {
|
if (isGitea) {
|
||||||
await deleteGiteaReleaseAsset(
|
await deleteGiteaReleaseAsset(github, releaseId, existingAsset.id);
|
||||||
github,
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
releaseId,
|
|
||||||
existingAsset.id,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
await github.rest.repos.deleteReleaseAsset({
|
await github.rest.repos.deleteReleaseAsset({
|
||||||
owner: owner,
|
owner,
|
||||||
repo: repo,
|
repo,
|
||||||
asset_id: existingAsset.id,
|
asset_id: existingAsset.id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -89,8 +86,8 @@ export async function uploadAssets(
|
|||||||
// 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),
|
||||||
owner: owner,
|
owner,
|
||||||
repo: repo,
|
repo,
|
||||||
release_id: releaseId,
|
release_id: releaseId,
|
||||||
}),
|
}),
|
||||||
retryAttempts + 1,
|
retryAttempts + 1,
|
||||||
|
|||||||
@@ -3,11 +3,23 @@ import { basename, extname, resolve } from 'node:path';
|
|||||||
|
|
||||||
import { getOctokit } from '@actions/github';
|
import { getOctokit } from '@actions/github';
|
||||||
|
|
||||||
|
import {
|
||||||
|
githubBaseUrl,
|
||||||
|
isGitea,
|
||||||
|
owner,
|
||||||
|
releaseAssetNamePattern,
|
||||||
|
repo,
|
||||||
|
updaterJsonPreferNsis,
|
||||||
|
} from './inputs';
|
||||||
import { uploadAssets } from './upload-release-assets';
|
import { uploadAssets } from './upload-release-assets';
|
||||||
import { deleteGiteaReleaseAsset, getAssetName, ghAssetName } from './utils';
|
import {
|
||||||
|
createArtifact,
|
||||||
|
deleteGiteaReleaseAsset,
|
||||||
|
getAssetName,
|
||||||
|
ghAssetName,
|
||||||
|
} from './utils';
|
||||||
|
|
||||||
import type { Artifact, TargetInfo } from './types';
|
import type { Artifact, TargetInfo } from './types';
|
||||||
import { createArtifact } from './utils';
|
|
||||||
|
|
||||||
type Platform = {
|
type Platform = {
|
||||||
signature: string;
|
signature: string;
|
||||||
@@ -24,8 +36,6 @@ type VersionContent = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export async function uploadVersionJSON(
|
export async function uploadVersionJSON(
|
||||||
owner: string,
|
|
||||||
repo: string,
|
|
||||||
version: string,
|
version: string,
|
||||||
notes: string,
|
notes: string,
|
||||||
tagName: string,
|
tagName: string,
|
||||||
@@ -33,11 +43,6 @@ export async function uploadVersionJSON(
|
|||||||
artifacts: Artifact[],
|
artifacts: Artifact[],
|
||||||
targetInfo: TargetInfo,
|
targetInfo: TargetInfo,
|
||||||
unzippedSig: boolean,
|
unzippedSig: boolean,
|
||||||
updaterJsonPreferNsis: boolean,
|
|
||||||
_retryAttempts: number,
|
|
||||||
githubBaseUrl: string,
|
|
||||||
isGitea: boolean,
|
|
||||||
releaseAssetNamePattern?: string,
|
|
||||||
) {
|
) {
|
||||||
if (process.env.GITHUB_TOKEN === undefined) {
|
if (process.env.GITHUB_TOKEN === undefined) {
|
||||||
throw new Error('GITHUB_TOKEN is required');
|
throw new Error('GITHUB_TOKEN is required');
|
||||||
@@ -57,8 +62,8 @@ export async function uploadVersionJSON(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const assets = await github.rest.repos.listReleaseAssets({
|
const assets = await github.rest.repos.listReleaseAssets({
|
||||||
owner: owner,
|
owner,
|
||||||
repo: repo,
|
repo,
|
||||||
release_id: releaseId,
|
release_id: releaseId,
|
||||||
per_page: 50,
|
per_page: 50,
|
||||||
});
|
});
|
||||||
@@ -308,12 +313,12 @@ export async function uploadVersionJSON(
|
|||||||
|
|
||||||
if (asset) {
|
if (asset) {
|
||||||
if (isGitea) {
|
if (isGitea) {
|
||||||
await deleteGiteaReleaseAsset(github, owner, repo, releaseId, asset.id);
|
await deleteGiteaReleaseAsset(github, releaseId, asset.id);
|
||||||
} else {
|
} else {
|
||||||
// https://docs.github.com/en/rest/releases/assets#update-a-release-asset
|
// https://docs.github.com/en/rest/releases/assets#update-a-release-asset
|
||||||
await github.rest.repos.deleteReleaseAsset({
|
await github.rest.repos.deleteReleaseAsset({
|
||||||
owner: owner,
|
owner,
|
||||||
repo: repo,
|
repo,
|
||||||
release_id: releaseId,
|
release_id: releaseId,
|
||||||
asset_id: asset.id,
|
asset_id: asset.id,
|
||||||
});
|
});
|
||||||
@@ -331,14 +336,10 @@ export async function uploadVersionJSON(
|
|||||||
});
|
});
|
||||||
|
|
||||||
await uploadAssets(
|
await uploadAssets(
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
releaseId,
|
releaseId,
|
||||||
[artifact],
|
[artifact],
|
||||||
// The whole step will be retried where `uploadVersionJSON` is called.
|
// The whole step will be retried where `uploadVersionJSON` is called.
|
||||||
// Just in case it's a quick http hickup we retry it once here as well.
|
// Just in case it's a quick http hickup we retry it once here as well.
|
||||||
1,
|
1,
|
||||||
githubBaseUrl,
|
|
||||||
isGitea,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,22 @@
|
|||||||
import { dirname } from 'node:path';
|
import { dirname } from 'node:path';
|
||||||
import GHArtifact from '@actions/artifact';
|
|
||||||
|
|
||||||
|
import GHArtifact from '@actions/artifact';
|
||||||
import { globbySync } from 'globby';
|
import { globbySync } from 'globby';
|
||||||
import { Artifact } from './types';
|
|
||||||
|
import { retryAttempts, workflowArtifactNamePattern } from './inputs';
|
||||||
import { getAssetName, retry } from './utils';
|
import { getAssetName, retry } from './utils';
|
||||||
|
|
||||||
export async function uploadWorkflowArtifacts(
|
import type { Artifact } from './types';
|
||||||
artifacts: Artifact[],
|
|
||||||
pattern: string | true,
|
export async function uploadWorkflowArtifacts(artifacts: Artifact[]) {
|
||||||
retryAttempts: number,
|
|
||||||
) {
|
|
||||||
for (const artifact of artifacts) {
|
for (const artifact of artifacts) {
|
||||||
if (artifact.workflowArtifactName) {
|
if (artifact.workflowArtifactName) {
|
||||||
let workflowArtifactName = artifact.workflowArtifactName;
|
let workflowArtifactName = artifact.workflowArtifactName;
|
||||||
if (typeof pattern === 'string') {
|
|
||||||
workflowArtifactName = getAssetName(artifact, pattern);
|
workflowArtifactName = getAssetName(
|
||||||
}
|
artifact,
|
||||||
|
workflowArtifactNamePattern,
|
||||||
|
);
|
||||||
|
|
||||||
let paths = [artifact.path];
|
let paths = [artifact.path];
|
||||||
if (artifact.ext === '.app') {
|
if (artifact.ext === '.app') {
|
||||||
|
|||||||
39
src/utils.ts
39
src/utils.ts
@@ -24,6 +24,7 @@ import type {
|
|||||||
} from './types';
|
} from './types';
|
||||||
import { GitHub } from '@actions/github/lib/utils';
|
import { GitHub } from '@actions/github/lib/utils';
|
||||||
import { findUpSync } from 'find-up-simple';
|
import { findUpSync } from 'find-up-simple';
|
||||||
|
import { owner, projectPath, repo } from './inputs';
|
||||||
|
|
||||||
/*** constants ***/
|
/*** constants ***/
|
||||||
export const extensions = [
|
export const extensions = [
|
||||||
@@ -125,6 +126,16 @@ export function getAssetName(asset: Artifact, pattern?: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function ghAssetName(
|
||||||
|
artifact: Artifact,
|
||||||
|
releaseAssetNamePattern?: string,
|
||||||
|
) {
|
||||||
|
return getAssetName(artifact, releaseAssetNamePattern)
|
||||||
|
.trim()
|
||||||
|
.replace(/[^a-zA-Z0-9_-]/g, '.')
|
||||||
|
.replace(/\.\./g, '.');
|
||||||
|
}
|
||||||
|
|
||||||
export function createArtifact({
|
export function createArtifact({
|
||||||
path,
|
path,
|
||||||
name,
|
name,
|
||||||
@@ -178,12 +189,12 @@ export function getPackageJson(root: string) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTauriDir(root: string): string | null {
|
export function getTauriDir(): string | null {
|
||||||
const tauriConfPaths = globbySync(
|
const tauriConfPaths = globbySync(
|
||||||
['**/tauri.conf.json', '**/tauri.conf.json5', '**/Tauri.toml'],
|
['**/tauri.conf.json', '**/tauri.conf.json5', '**/Tauri.toml'],
|
||||||
{
|
{
|
||||||
gitignore: true,
|
gitignore: true,
|
||||||
cwd: root,
|
cwd: projectPath,
|
||||||
// Forcefully ignore target and node_modules dirs
|
// Forcefully ignore target and node_modules dirs
|
||||||
ignore: ['**/target', '**/node_modules'],
|
ignore: ['**/target', '**/node_modules'],
|
||||||
},
|
},
|
||||||
@@ -193,7 +204,7 @@ export function getTauriDir(root: string): string | null {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolve(root, tauriConfPaths[0], '..');
|
return resolve(projectPath, tauriConfPaths[0], '..');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getWorkspaceDir(dir: string): string | null {
|
export function getWorkspaceDir(dir: string): string | null {
|
||||||
@@ -469,12 +480,8 @@ export async function execCommand(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getInfo(
|
export function getInfo(targetInfo?: TargetInfo, configFlag?: string): Info {
|
||||||
root: string,
|
const tauriDir = getTauriDir();
|
||||||
targetInfo?: TargetInfo,
|
|
||||||
configFlag?: string,
|
|
||||||
): Info {
|
|
||||||
const tauriDir = getTauriDir(root);
|
|
||||||
if (tauriDir !== null) {
|
if (tauriDir !== null) {
|
||||||
let name;
|
let name;
|
||||||
let version;
|
let version;
|
||||||
@@ -488,7 +495,7 @@ export function getInfo(
|
|||||||
config.mergePlatformConfig(tauriDir, targetInfo.platform);
|
config.mergePlatformConfig(tauriDir, targetInfo.platform);
|
||||||
}
|
}
|
||||||
if (configFlag) {
|
if (configFlag) {
|
||||||
config.mergeUserConfig(root, configFlag);
|
config.mergeUserConfig(projectPath, configFlag);
|
||||||
}
|
}
|
||||||
|
|
||||||
name = config?.productName;
|
name = config?.productName;
|
||||||
@@ -584,8 +591,6 @@ export async function retry(
|
|||||||
// This is a workaround since Gitea's API is incompatible with the GitHub API
|
// This is a workaround since Gitea's API is incompatible with the GitHub API
|
||||||
export function deleteGiteaReleaseAsset(
|
export function deleteGiteaReleaseAsset(
|
||||||
github: InstanceType<typeof GitHub>,
|
github: InstanceType<typeof GitHub>,
|
||||||
owner: string,
|
|
||||||
repo: string,
|
|
||||||
releaseId: number,
|
releaseId: number,
|
||||||
assetId: number,
|
assetId: number,
|
||||||
) {
|
) {
|
||||||
@@ -600,14 +605,4 @@ 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.
|
||||||
|
|||||||
Reference in New Issue
Block a user