refactor: Merge workspace into single package. (#362)
* refactor repo into one package * take pnpm for a test drive * add tslib again * fix dist path in action.yml * split up core script. add eslint * don't early return artifacts on macos * up node version * update deps * fix change files * rebuild dist
@@ -6,7 +6,7 @@
|
|||||||
"getPublishedVersion": "npm view ${ pkgFile.pkg.name } version",
|
"getPublishedVersion": "npm view ${ pkgFile.pkg.name } version",
|
||||||
"prepublish": [
|
"prepublish": [
|
||||||
{
|
{
|
||||||
"command": "yarn",
|
"command": "pnpm install",
|
||||||
"dryRunCommand": true
|
"dryRunCommand": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -29,18 +29,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"@tauri-apps/action-core": {
|
|
||||||
"path": "./packages/core",
|
|
||||||
"manager": "javascript",
|
|
||||||
"assets": [
|
|
||||||
{
|
|
||||||
"path": "./packages/core/tauri-apps-action-core-${ pkgFile.version }.tgz",
|
|
||||||
"name": "action-core-${ pkgFile.version }.tgz"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"action": {
|
"action": {
|
||||||
"path": "./packages/action",
|
"path": "./",
|
||||||
"manager": "javascript",
|
"manager": "javascript",
|
||||||
"publish": [
|
"publish": [
|
||||||
"git tag v${ pkgFile.versionMajor } -f",
|
"git tag v${ pkgFile.versionMajor } -f",
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
---
|
---
|
||||||
"@tauri-apps/action-core": patch
|
|
||||||
"action": patch
|
"action": patch
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
"@tauri-apps/action-core": patch
|
'action': patch
|
||||||
---
|
---
|
||||||
|
|
||||||
Replace `_` and `.` with `-` in the product name on Linux.
|
Replace `_` and `.` with `-` in the product name on Linux.
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
"@tauri-apps/action-core": patch
|
'action': patch
|
||||||
"action": patch
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Fixes usage with `vue-cli-plugin-tauri`.
|
Fixes usage with `vue-cli-plugin-tauri`.
|
||||||
|
|||||||
20
.eslintrc.cjs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
node: true,
|
||||||
|
es2021: true,
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
'prettier',
|
||||||
|
'eslint:recommended',
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
],
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 'latest',
|
||||||
|
sourceType: 'module',
|
||||||
|
},
|
||||||
|
plugins: ['@typescript-eslint'],
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/ban-ts-comment': 'off',
|
||||||
|
},
|
||||||
|
};
|
||||||
2
.github/workflows/covector-status.yml
vendored
@@ -6,7 +6,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: covector status
|
- name: covector status
|
||||||
|
|||||||
@@ -9,13 +9,17 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/setup-node@v1
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 12
|
node-version: 16
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
- name: install pnpm
|
||||||
|
uses: pnpm/action-setup@v2
|
||||||
|
with:
|
||||||
|
version: 7.x.x
|
||||||
- name: git config
|
- name: git config
|
||||||
run: |
|
run: |
|
||||||
git config --global user.name "${{ github.event.pusher.name }}"
|
git config --global user.name "${{ github.event.pusher.name }}"
|
||||||
|
|||||||
8
.github/workflows/test-action.yml
vendored
@@ -15,18 +15,22 @@ jobs:
|
|||||||
- name: setup node
|
- name: setup node
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: 14
|
node-version: 16
|
||||||
- name: install Rust stable
|
- name: install Rust stable
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
|
- name: install pnpm
|
||||||
|
uses: pnpm/action-setup@v2
|
||||||
|
with:
|
||||||
|
version: 7.x.x
|
||||||
- name: install dependencies (ubuntu only)
|
- name: install dependencies (ubuntu only)
|
||||||
if: matrix.platform == 'ubuntu-latest'
|
if: matrix.platform == 'ubuntu-latest'
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev librsvg2-dev patchelf
|
sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev librsvg2-dev patchelf
|
||||||
- name: install example dependencies
|
- name: install example dependencies
|
||||||
run: yarn
|
run: pnpm install
|
||||||
working-directory: ./packages/action/__fixtures__/example
|
working-directory: ./packages/action/__fixtures__/example
|
||||||
- uses: ./
|
- uses: ./
|
||||||
env:
|
env:
|
||||||
|
|||||||
7
.gitignore
vendored
@@ -44,10 +44,3 @@ target
|
|||||||
|
|
||||||
# lockfiles, as a lib we don't need to lock
|
# lockfiles, as a lib we don't need to lock
|
||||||
yarn.lock
|
yarn.lock
|
||||||
|
|
||||||
# rollup output
|
|
||||||
dist
|
|
||||||
# but we want the action dist
|
|
||||||
!packages/action/dist
|
|
||||||
!packages/action/dist/**
|
|
||||||
!packages/action/__fixtures__/**/dist
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
@@ -50,4 +50,4 @@ outputs:
|
|||||||
description: 'The paths of the generated artifacts'
|
description: 'The paths of the generated artifacts'
|
||||||
runs:
|
runs:
|
||||||
using: 'node16'
|
using: 'node16'
|
||||||
main: 'packages/action/dist/index.js'
|
main: 'dist/index.js'
|
||||||
|
|||||||
7
dist/index.js
vendored
Normal file
49
package.json
@@ -1,12 +1,47 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"name": "tauri-action",
|
||||||
"workspaces": [
|
"version": "0.3.1",
|
||||||
"packages/core",
|
"description": "Tauri GitHub Action",
|
||||||
"packages/cli",
|
"author": "Lucas Nogueira <lucas@tauri.studio>",
|
||||||
"packages/action"
|
"license": "MIT",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"build": "ncc build src/index.ts -o dist -m",
|
||||||
|
"lint": "eslint src/**"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/tauri-apps/tauri-action.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"actions",
|
||||||
|
"tauri"
|
||||||
],
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/core": "1.10.0",
|
||||||
|
"@actions/github": "5.1.1",
|
||||||
|
"@iarna/toml": "2.2.5",
|
||||||
|
"execa": "6.1.0",
|
||||||
|
"glob-gitignore": "^1.0.14",
|
||||||
|
"ignore": "5.2.4",
|
||||||
|
"json5": "2.2.3",
|
||||||
|
"string-argv": "0.3.1",
|
||||||
|
"tslib": "2.5.0"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"covector": "0.7.3",
|
"@types/node": "16.18.11",
|
||||||
"prettier": "^2.8.0"
|
"@typescript-eslint/eslint-plugin": "5.49.0",
|
||||||
|
"@typescript-eslint/parser": "5.49.0",
|
||||||
|
"@vercel/ncc": "0.36.1",
|
||||||
|
"covector": "0.8.0",
|
||||||
|
"eslint": "8.33.0",
|
||||||
|
"eslint-config-prettier": "8.6.0",
|
||||||
|
"eslint-config-standard-with-typescript": "33.0.0",
|
||||||
|
"eslint-plugin-import": "2.27.5",
|
||||||
|
"eslint-plugin-n": "15.6.1",
|
||||||
|
"eslint-plugin-promise": "6.1.1",
|
||||||
|
"prettier": "2.8.3",
|
||||||
|
"typescript": "4.9.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
450
packages/action/dist/543.index.js
vendored
@@ -1,450 +0,0 @@
|
|||||||
export const id = 543;
|
|
||||||
export const ids = [543];
|
|
||||||
export const modules = {
|
|
||||||
|
|
||||||
/***/ 543:
|
|
||||||
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
||||||
|
|
||||||
__webpack_require__.r(__webpack_exports__);
|
|
||||||
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
||||||
/* harmony export */ "toFormData": () => (/* binding */ toFormData)
|
|
||||||
/* harmony export */ });
|
|
||||||
/* harmony import */ var fetch_blob_from_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7907);
|
|
||||||
/* harmony import */ var formdata_polyfill_esm_min_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6296);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let s = 0;
|
|
||||||
const S = {
|
|
||||||
START_BOUNDARY: s++,
|
|
||||||
HEADER_FIELD_START: s++,
|
|
||||||
HEADER_FIELD: s++,
|
|
||||||
HEADER_VALUE_START: s++,
|
|
||||||
HEADER_VALUE: s++,
|
|
||||||
HEADER_VALUE_ALMOST_DONE: s++,
|
|
||||||
HEADERS_ALMOST_DONE: s++,
|
|
||||||
PART_DATA_START: s++,
|
|
||||||
PART_DATA: s++,
|
|
||||||
END: s++
|
|
||||||
};
|
|
||||||
|
|
||||||
let f = 1;
|
|
||||||
const F = {
|
|
||||||
PART_BOUNDARY: f,
|
|
||||||
LAST_BOUNDARY: f *= 2
|
|
||||||
};
|
|
||||||
|
|
||||||
const LF = 10;
|
|
||||||
const CR = 13;
|
|
||||||
const SPACE = 32;
|
|
||||||
const HYPHEN = 45;
|
|
||||||
const COLON = 58;
|
|
||||||
const A = 97;
|
|
||||||
const Z = 122;
|
|
||||||
|
|
||||||
const lower = c => c | 0x20;
|
|
||||||
|
|
||||||
const noop = () => {};
|
|
||||||
|
|
||||||
class MultipartParser {
|
|
||||||
/**
|
|
||||||
* @param {string} boundary
|
|
||||||
*/
|
|
||||||
constructor(boundary) {
|
|
||||||
this.index = 0;
|
|
||||||
this.flags = 0;
|
|
||||||
|
|
||||||
this.onHeaderEnd = noop;
|
|
||||||
this.onHeaderField = noop;
|
|
||||||
this.onHeadersEnd = noop;
|
|
||||||
this.onHeaderValue = noop;
|
|
||||||
this.onPartBegin = noop;
|
|
||||||
this.onPartData = noop;
|
|
||||||
this.onPartEnd = noop;
|
|
||||||
|
|
||||||
this.boundaryChars = {};
|
|
||||||
|
|
||||||
boundary = '\r\n--' + boundary;
|
|
||||||
const ui8a = new Uint8Array(boundary.length);
|
|
||||||
for (let i = 0; i < boundary.length; i++) {
|
|
||||||
ui8a[i] = boundary.charCodeAt(i);
|
|
||||||
this.boundaryChars[ui8a[i]] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.boundary = ui8a;
|
|
||||||
this.lookbehind = new Uint8Array(this.boundary.length + 8);
|
|
||||||
this.state = S.START_BOUNDARY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Uint8Array} data
|
|
||||||
*/
|
|
||||||
write(data) {
|
|
||||||
let i = 0;
|
|
||||||
const length_ = data.length;
|
|
||||||
let previousIndex = this.index;
|
|
||||||
let {lookbehind, boundary, boundaryChars, index, state, flags} = this;
|
|
||||||
const boundaryLength = this.boundary.length;
|
|
||||||
const boundaryEnd = boundaryLength - 1;
|
|
||||||
const bufferLength = data.length;
|
|
||||||
let c;
|
|
||||||
let cl;
|
|
||||||
|
|
||||||
const mark = name => {
|
|
||||||
this[name + 'Mark'] = i;
|
|
||||||
};
|
|
||||||
|
|
||||||
const clear = name => {
|
|
||||||
delete this[name + 'Mark'];
|
|
||||||
};
|
|
||||||
|
|
||||||
const callback = (callbackSymbol, start, end, ui8a) => {
|
|
||||||
if (start === undefined || start !== end) {
|
|
||||||
this[callbackSymbol](ui8a && ui8a.subarray(start, end));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const dataCallback = (name, clear) => {
|
|
||||||
const markSymbol = name + 'Mark';
|
|
||||||
if (!(markSymbol in this)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clear) {
|
|
||||||
callback(name, this[markSymbol], i, data);
|
|
||||||
delete this[markSymbol];
|
|
||||||
} else {
|
|
||||||
callback(name, this[markSymbol], data.length, data);
|
|
||||||
this[markSymbol] = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (i = 0; i < length_; i++) {
|
|
||||||
c = data[i];
|
|
||||||
|
|
||||||
switch (state) {
|
|
||||||
case S.START_BOUNDARY:
|
|
||||||
if (index === boundary.length - 2) {
|
|
||||||
if (c === HYPHEN) {
|
|
||||||
flags |= F.LAST_BOUNDARY;
|
|
||||||
} else if (c !== CR) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
break;
|
|
||||||
} else if (index - 1 === boundary.length - 2) {
|
|
||||||
if (flags & F.LAST_BOUNDARY && c === HYPHEN) {
|
|
||||||
state = S.END;
|
|
||||||
flags = 0;
|
|
||||||
} else if (!(flags & F.LAST_BOUNDARY) && c === LF) {
|
|
||||||
index = 0;
|
|
||||||
callback('onPartBegin');
|
|
||||||
state = S.HEADER_FIELD_START;
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c !== boundary[index + 2]) {
|
|
||||||
index = -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c === boundary[index + 2]) {
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case S.HEADER_FIELD_START:
|
|
||||||
state = S.HEADER_FIELD;
|
|
||||||
mark('onHeaderField');
|
|
||||||
index = 0;
|
|
||||||
// falls through
|
|
||||||
case S.HEADER_FIELD:
|
|
||||||
if (c === CR) {
|
|
||||||
clear('onHeaderField');
|
|
||||||
state = S.HEADERS_ALMOST_DONE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
if (c === HYPHEN) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c === COLON) {
|
|
||||||
if (index === 1) {
|
|
||||||
// empty header field
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dataCallback('onHeaderField', true);
|
|
||||||
state = S.HEADER_VALUE_START;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
cl = lower(c);
|
|
||||||
if (cl < A || cl > Z) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case S.HEADER_VALUE_START:
|
|
||||||
if (c === SPACE) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
mark('onHeaderValue');
|
|
||||||
state = S.HEADER_VALUE;
|
|
||||||
// falls through
|
|
||||||
case S.HEADER_VALUE:
|
|
||||||
if (c === CR) {
|
|
||||||
dataCallback('onHeaderValue', true);
|
|
||||||
callback('onHeaderEnd');
|
|
||||||
state = S.HEADER_VALUE_ALMOST_DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case S.HEADER_VALUE_ALMOST_DONE:
|
|
||||||
if (c !== LF) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
state = S.HEADER_FIELD_START;
|
|
||||||
break;
|
|
||||||
case S.HEADERS_ALMOST_DONE:
|
|
||||||
if (c !== LF) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
callback('onHeadersEnd');
|
|
||||||
state = S.PART_DATA_START;
|
|
||||||
break;
|
|
||||||
case S.PART_DATA_START:
|
|
||||||
state = S.PART_DATA;
|
|
||||||
mark('onPartData');
|
|
||||||
// falls through
|
|
||||||
case S.PART_DATA:
|
|
||||||
previousIndex = index;
|
|
||||||
|
|
||||||
if (index === 0) {
|
|
||||||
// boyer-moore derrived algorithm to safely skip non-boundary data
|
|
||||||
i += boundaryEnd;
|
|
||||||
while (i < bufferLength && !(data[i] in boundaryChars)) {
|
|
||||||
i += boundaryLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
i -= boundaryEnd;
|
|
||||||
c = data[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index < boundary.length) {
|
|
||||||
if (boundary[index] === c) {
|
|
||||||
if (index === 0) {
|
|
||||||
dataCallback('onPartData', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
} else {
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
} else if (index === boundary.length) {
|
|
||||||
index++;
|
|
||||||
if (c === CR) {
|
|
||||||
// CR = part boundary
|
|
||||||
flags |= F.PART_BOUNDARY;
|
|
||||||
} else if (c === HYPHEN) {
|
|
||||||
// HYPHEN = end boundary
|
|
||||||
flags |= F.LAST_BOUNDARY;
|
|
||||||
} else {
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
} else if (index - 1 === boundary.length) {
|
|
||||||
if (flags & F.PART_BOUNDARY) {
|
|
||||||
index = 0;
|
|
||||||
if (c === LF) {
|
|
||||||
// unset the PART_BOUNDARY flag
|
|
||||||
flags &= ~F.PART_BOUNDARY;
|
|
||||||
callback('onPartEnd');
|
|
||||||
callback('onPartBegin');
|
|
||||||
state = S.HEADER_FIELD_START;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (flags & F.LAST_BOUNDARY) {
|
|
||||||
if (c === HYPHEN) {
|
|
||||||
callback('onPartEnd');
|
|
||||||
state = S.END;
|
|
||||||
flags = 0;
|
|
||||||
} else {
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index > 0) {
|
|
||||||
// when matching a possible boundary, keep a lookbehind reference
|
|
||||||
// in case it turns out to be a false lead
|
|
||||||
lookbehind[index - 1] = c;
|
|
||||||
} else if (previousIndex > 0) {
|
|
||||||
// if our boundary turned out to be rubbish, the captured lookbehind
|
|
||||||
// belongs to partData
|
|
||||||
const _lookbehind = new Uint8Array(lookbehind.buffer, lookbehind.byteOffset, lookbehind.byteLength);
|
|
||||||
callback('onPartData', 0, previousIndex, _lookbehind);
|
|
||||||
previousIndex = 0;
|
|
||||||
mark('onPartData');
|
|
||||||
|
|
||||||
// reconsider the current character even so it interrupted the sequence
|
|
||||||
// it could be the beginning of a new sequence
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case S.END:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error(`Unexpected state entered: ${state}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dataCallback('onHeaderField');
|
|
||||||
dataCallback('onHeaderValue');
|
|
||||||
dataCallback('onPartData');
|
|
||||||
|
|
||||||
// Update properties for the next call
|
|
||||||
this.index = index;
|
|
||||||
this.state = state;
|
|
||||||
this.flags = flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
end() {
|
|
||||||
if ((this.state === S.HEADER_FIELD_START && this.index === 0) ||
|
|
||||||
(this.state === S.PART_DATA && this.index === this.boundary.length)) {
|
|
||||||
this.onPartEnd();
|
|
||||||
} else if (this.state !== S.END) {
|
|
||||||
throw new Error('MultipartParser.end(): stream ended unexpectedly');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function _fileName(headerValue) {
|
|
||||||
// matches either a quoted-string or a token (RFC 2616 section 19.5.1)
|
|
||||||
const m = headerValue.match(/\bfilename=("(.*?)"|([^()<>@,;:\\"/[\]?={}\s\t]+))($|;\s)/i);
|
|
||||||
if (!m) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const match = m[2] || m[3] || '';
|
|
||||||
let filename = match.slice(match.lastIndexOf('\\') + 1);
|
|
||||||
filename = filename.replace(/%22/g, '"');
|
|
||||||
filename = filename.replace(/&#(\d{4});/g, (m, code) => {
|
|
||||||
return String.fromCharCode(code);
|
|
||||||
});
|
|
||||||
return filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function toFormData(Body, ct) {
|
|
||||||
if (!/multipart/i.test(ct)) {
|
|
||||||
throw new TypeError('Failed to fetch');
|
|
||||||
}
|
|
||||||
|
|
||||||
const m = ct.match(/boundary=(?:"([^"]+)"|([^;]+))/i);
|
|
||||||
|
|
||||||
if (!m) {
|
|
||||||
throw new TypeError('no or bad content-type header, no multipart boundary');
|
|
||||||
}
|
|
||||||
|
|
||||||
const parser = new MultipartParser(m[1] || m[2]);
|
|
||||||
|
|
||||||
let headerField;
|
|
||||||
let headerValue;
|
|
||||||
let entryValue;
|
|
||||||
let entryName;
|
|
||||||
let contentType;
|
|
||||||
let filename;
|
|
||||||
const entryChunks = [];
|
|
||||||
const formData = new formdata_polyfill_esm_min_js__WEBPACK_IMPORTED_MODULE_1__/* .FormData */ .Ct();
|
|
||||||
|
|
||||||
const onPartData = ui8a => {
|
|
||||||
entryValue += decoder.decode(ui8a, {stream: true});
|
|
||||||
};
|
|
||||||
|
|
||||||
const appendToFile = ui8a => {
|
|
||||||
entryChunks.push(ui8a);
|
|
||||||
};
|
|
||||||
|
|
||||||
const appendFileToFormData = () => {
|
|
||||||
const file = new fetch_blob_from_js__WEBPACK_IMPORTED_MODULE_0__/* .File */ .$B(entryChunks, filename, {type: contentType});
|
|
||||||
formData.append(entryName, file);
|
|
||||||
};
|
|
||||||
|
|
||||||
const appendEntryToFormData = () => {
|
|
||||||
formData.append(entryName, entryValue);
|
|
||||||
};
|
|
||||||
|
|
||||||
const decoder = new TextDecoder('utf-8');
|
|
||||||
decoder.decode();
|
|
||||||
|
|
||||||
parser.onPartBegin = function () {
|
|
||||||
parser.onPartData = onPartData;
|
|
||||||
parser.onPartEnd = appendEntryToFormData;
|
|
||||||
|
|
||||||
headerField = '';
|
|
||||||
headerValue = '';
|
|
||||||
entryValue = '';
|
|
||||||
entryName = '';
|
|
||||||
contentType = '';
|
|
||||||
filename = null;
|
|
||||||
entryChunks.length = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
parser.onHeaderField = function (ui8a) {
|
|
||||||
headerField += decoder.decode(ui8a, {stream: true});
|
|
||||||
};
|
|
||||||
|
|
||||||
parser.onHeaderValue = function (ui8a) {
|
|
||||||
headerValue += decoder.decode(ui8a, {stream: true});
|
|
||||||
};
|
|
||||||
|
|
||||||
parser.onHeaderEnd = function () {
|
|
||||||
headerValue += decoder.decode();
|
|
||||||
headerField = headerField.toLowerCase();
|
|
||||||
|
|
||||||
if (headerField === 'content-disposition') {
|
|
||||||
// matches either a quoted-string or a token (RFC 2616 section 19.5.1)
|
|
||||||
const m = headerValue.match(/\bname=("([^"]*)"|([^()<>@,;:\\"/[\]?={}\s\t]+))/i);
|
|
||||||
|
|
||||||
if (m) {
|
|
||||||
entryName = m[2] || m[3] || '';
|
|
||||||
}
|
|
||||||
|
|
||||||
filename = _fileName(headerValue);
|
|
||||||
|
|
||||||
if (filename) {
|
|
||||||
parser.onPartData = appendToFile;
|
|
||||||
parser.onPartEnd = appendFileToFormData;
|
|
||||||
}
|
|
||||||
} else if (headerField === 'content-type') {
|
|
||||||
contentType = headerValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
headerValue = '';
|
|
||||||
headerField = '';
|
|
||||||
};
|
|
||||||
|
|
||||||
for await (const chunk of Body) {
|
|
||||||
parser.write(chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
parser.end();
|
|
||||||
|
|
||||||
return formData;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***/ })
|
|
||||||
|
|
||||||
};
|
|
||||||
7
packages/action/dist/index.js
vendored
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "tauri-action",
|
|
||||||
"version": "0.3.1",
|
|
||||||
"description": "Tauri GitHub Action",
|
|
||||||
"author": "Lucas Nogueira <lucas@tauri.studio>",
|
|
||||||
"license": "MIT",
|
|
||||||
"main": "dist/index.js",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"build": "ncc build src/index.ts -o dist -m"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/tauri-apps/tauri-action.git"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"actions",
|
|
||||||
"tauri"
|
|
||||||
],
|
|
||||||
"dependencies": {
|
|
||||||
"@actions/core": "1.10.0",
|
|
||||||
"@actions/github": "5.1.1",
|
|
||||||
"@tauri-apps/action-core": "0.3.1",
|
|
||||||
"node-fetch": "3.3.0",
|
|
||||||
"string-argv": "0.3.1",
|
|
||||||
"tslib": "2.4.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/node": "16.18.11",
|
|
||||||
"@vercel/ncc": "0.36.0",
|
|
||||||
"rollup": "2.79.1",
|
|
||||||
"typescript": "4.9.4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
import path from 'path';
|
|
||||||
|
|
||||||
const extensions = [
|
|
||||||
'.app.tar.gz.sig',
|
|
||||||
'.app.tar.gz',
|
|
||||||
'.dmg',
|
|
||||||
'.AppImage.tar.gz.sig',
|
|
||||||
'.AppImage.tar.gz',
|
|
||||||
'.AppImage',
|
|
||||||
'.deb',
|
|
||||||
'.msi.zip.sig',
|
|
||||||
'.msi.zip',
|
|
||||||
'.msi',
|
|
||||||
];
|
|
||||||
|
|
||||||
export function getAssetName(assetPath: string) {
|
|
||||||
const basename = path.basename(assetPath);
|
|
||||||
const exts = extensions.filter((s) => basename.includes(s));
|
|
||||||
const ext = exts[0] || path.extname(assetPath);
|
|
||||||
const filename = basename.replace(ext, '');
|
|
||||||
|
|
||||||
let arch = '';
|
|
||||||
if (ext === '.app.tar.gz.sig' || ext === '.app.tar.gz') {
|
|
||||||
arch = assetPath.includes('universal-apple-darwin')
|
|
||||||
? '_universal'
|
|
||||||
: assetPath.includes('aarch64-apple-darwin')
|
|
||||||
? '_aarch64'
|
|
||||||
: '_x64';
|
|
||||||
}
|
|
||||||
|
|
||||||
return assetPath.includes(`${path.sep}debug${path.sep}`)
|
|
||||||
? `${filename}-debug${arch}${ext}`
|
|
||||||
: `${filename}${arch}${ext}`;
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"target": "es2015",
|
|
||||||
"moduleResolution": "node"
|
|
||||||
},
|
|
||||||
"include": ["."]
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import { run } from '../dist/index.js';
|
|
||||||
run();
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
import { join, resolve } from 'path';
|
|
||||||
import { existsSync } from 'fs';
|
|
||||||
import { buildProject } from '@tauri-apps/action-core';
|
|
||||||
import type { BuildOptions } from '@tauri-apps/action-core';
|
|
||||||
import parseArgs from 'minimist';
|
|
||||||
|
|
||||||
export async function run(): Promise<void> {
|
|
||||||
const argv = parseArgs(process.argv.slice(2), {
|
|
||||||
string: [
|
|
||||||
'project-path',
|
|
||||||
'config-path',
|
|
||||||
'dist-path',
|
|
||||||
'icon-path',
|
|
||||||
'tauri-script',
|
|
||||||
],
|
|
||||||
boolean: ['global-tauri', 'include-debug'],
|
|
||||||
default: {
|
|
||||||
'config-path': 'tauri.conf.json',
|
|
||||||
'project-path': '',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const projectPath = resolve(process.cwd(), argv['project-path']);
|
|
||||||
const configPath = join(projectPath, argv['config-path']);
|
|
||||||
const distPath = argv['dist-path'];
|
|
||||||
const iconPath = argv['icon-path'];
|
|
||||||
const includeDebug = argv['include-debug'];
|
|
||||||
const tauriScript = argv['tauri-script'];
|
|
||||||
const args = argv._;
|
|
||||||
|
|
||||||
const options: BuildOptions = {
|
|
||||||
configPath: existsSync(configPath) ? configPath : null,
|
|
||||||
distPath,
|
|
||||||
iconPath,
|
|
||||||
tauriScript,
|
|
||||||
args,
|
|
||||||
};
|
|
||||||
const artifacts = await buildProject(projectPath, false, options);
|
|
||||||
if (includeDebug) {
|
|
||||||
const debugArtifacts = await buildProject(projectPath, true, options);
|
|
||||||
artifacts.push(...debugArtifacts);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (artifacts.length === 0) {
|
|
||||||
throw new Error('No artifacts were found.');
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Artifacts: ${artifacts}.`);
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@tauri-apps/action-cli",
|
|
||||||
"version": "0.0.10",
|
|
||||||
"description": "Tauri GitHub Action CLI",
|
|
||||||
"author": "Lucas Nogueira <lucas@tauri.studio>",
|
|
||||||
"license": "MIT",
|
|
||||||
"main": "dist",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"build": "rollup --config",
|
|
||||||
"prepublishOnly": "rollup --config"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/tauri-apps/tauri-action.git"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@tauri-apps/action-core": "0.2.0",
|
|
||||||
"minimist": "1.2.7",
|
|
||||||
"tslib": "2.4.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@rollup/plugin-typescript": "10.0.1",
|
|
||||||
"@types/minimist": "1.2.2",
|
|
||||||
"rollup": "2.79.1",
|
|
||||||
"typescript": "4.9.4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import typescript from '@rollup/plugin-typescript';
|
|
||||||
import pkg from './package.json';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
treeshake: true,
|
|
||||||
perf: true,
|
|
||||||
input: { index: 'index.ts' },
|
|
||||||
output: {
|
|
||||||
dir: 'dist',
|
|
||||||
format: 'esm',
|
|
||||||
entryFileNames: '[name].js',
|
|
||||||
exports: 'named',
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
typescript({
|
|
||||||
allowSyntheticDefaultImports: true,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
external: [...Object.keys(pkg.dependencies || {}), 'path'],
|
|
||||||
watch: {
|
|
||||||
chokidar: true,
|
|
||||||
include: 'src/**',
|
|
||||||
exclude: 'node_modules/**',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
# Changelog
|
|
||||||
|
|
||||||
## \[0.3.1]
|
|
||||||
|
|
||||||
- Added the `bundleIdentifier` input to modify Tauri's default bundle identifier when initializing a new Tauri app.
|
|
||||||
- [743a37f](https://www.github.com/tauri-apps/tauri-action/commit/743a37fd53cbdd122910b818b9bef7b7aa019134) feat(core): add bundle identifier option ([#263](https://www.github.com/tauri-apps/tauri-action/pull/263)) on 2022-05-11
|
|
||||||
- Added support to loading version from JSON file in `tauri.conf.json > package > version`.
|
|
||||||
- [16a8f02](https://www.github.com/tauri-apps/tauri-action/commit/16a8f02ad9b4cff2a0ed6205c7418c36f3e49fd0) build(action): rebuild after fixing version parse error ([#268](https://www.github.com/tauri-apps/tauri-action/pull/268)) on 2022-05-28
|
|
||||||
|
|
||||||
## \[0.3.0]
|
|
||||||
|
|
||||||
- Added support to JSON5 on `tauri.conf.json[5]`.
|
|
||||||
- [b9ce5d7](https://www.github.com/tauri-apps/tauri-action/commit/b9ce5d7dc68082d21d30a60103b0ab8c5ddae3a1) feat: add JSON5 support ([#229](https://www.github.com/tauri-apps/tauri-action/pull/229)) on 2022-02-20
|
|
||||||
- Update to Tauri release candidate.
|
|
||||||
- [4d70258](https://www.github.com/tauri-apps/tauri-action/commit/4d7025802c5238ef60a62d33ef8c5378637948bb) fix: Change msi naming scheme for recent Tauri upgrades ([#227](https://www.github.com/tauri-apps/tauri-action/pull/227)) on 2022-02-20
|
|
||||||
- Added support to Cargo workspaces.
|
|
||||||
- [8e430cc](https://www.github.com/tauri-apps/tauri-action/commit/8e430cc7b0fab28f0a7768f2157933c94f8724f6) feat: cargo workspace support, closes [#196](https://www.github.com/tauri-apps/tauri-action/pull/196) ([#198](https://www.github.com/tauri-apps/tauri-action/pull/198)) on 2021-12-10
|
|
||||||
|
|
||||||
## \[0.2.0]
|
|
||||||
|
|
||||||
- Removed the `preferGlobal` and `npmScript` inputs and added a `tauriScript` option.
|
|
||||||
- [a1050c9](https://www.github.com/tauri-apps/tauri-action/commit/a1050c9ec8903fc5c43696da7f07dcfc89475104) refactor: add `tauriScript` input, remove `preferGlobal` and `npmScript` ([#183](https://www.github.com/tauri-apps/tauri-action/pull/183)) on 2021-11-01
|
|
||||||
|
|
||||||
## \[0.1.3]
|
|
||||||
|
|
||||||
- Linux: Upload AppImage updater artifacts if available.
|
|
||||||
macOS: Replace `[AppName].app.tgz` to `[AppName].app.tar.gz` to align with updater artifacts.
|
|
||||||
- [e7266ff](https://www.github.com/tauri-apps/tauri-action/commit/e7266fff1b42c35bfd7ff359d5c6a91ad1308dea) fix(action): Upload AppImage updater artifacts when available ([#163](https://www.github.com/tauri-apps/tauri-action/pull/163)) on 2021-08-31
|
|
||||||
- Fix incorrect version being used in release names
|
|
||||||
- [110a0c6](https://www.github.com/tauri-apps/tauri-action/commit/110a0c6da6de9aa85c8e3186ad642650ebc95ab0) Fix version lookup ([#160](https://www.github.com/tauri-apps/tauri-action/pull/160)) on 2021-09-01
|
|
||||||
|
|
||||||
## \[0.1.2]
|
|
||||||
|
|
||||||
- Adds `args` option to pass arguments to the tauri command.
|
|
||||||
- [f564b01](https://www.github.com/tauri-apps/tauri-action/commit/f564b01e52fbf240e5e5c12577dd10625fe83580) feat: add `args` option, closes [#131](https://www.github.com/tauri-apps/tauri-action/pull/131) ([#134](https://www.github.com/tauri-apps/tauri-action/pull/134)) on 2021-05-13
|
|
||||||
- Fixes `execCommand` usage.
|
|
||||||
- [b4b20f9](https://www.github.com/tauri-apps/tauri-action/commit/b4b20f94709829e5e974255aa8034c78e70bb5d1) fix(core): command execution ([#132](https://www.github.com/tauri-apps/tauri-action/pull/132)) on 2021-05-11
|
|
||||||
- Include updater artifacts if available.
|
|
||||||
- [0e9704e](https://www.github.com/tauri-apps/tauri-action/commit/0e9704eb73bcadd1c6acb3a2e9a73a100465db58) Add updater artifacts when available ([#129](https://www.github.com/tauri-apps/tauri-action/pull/129)) on 2021-05-13
|
|
||||||
|
|
||||||
## \[0.1.1]
|
|
||||||
|
|
||||||
- Fixes `Artifacts not found` error on Linux when the `productName` is converted to `kebab-case`.
|
|
||||||
- [e6aa180](https://www.github.com/tauri-apps/tauri-action/commit/e6aa1807b6d2c80de70f78fb945e11a659037837) fix(core): product name on Linux is converted to kebab-case ([#125](https://www.github.com/tauri-apps/tauri-action/pull/125)) on 2021-04-29
|
|
||||||
|
|
||||||
## \[0.1.0]
|
|
||||||
|
|
||||||
- Update to Tauri beta release candidate.
|
|
||||||
- [b874256](https://github.com/tauri-apps/tauri-action/commit/b87425614119f70be189fddd40a403481b91a328) refactor: rewrite as yarn workspace, add cli as test tool ([#98](https://github.com/tauri-apps/tauri-action/pull/98)) on 2021-04-26
|
|
||||||
- [dbbc6b4](https://github.com/tauri-apps/tauri-action/commit/dbbc6b4e604ce66a84108e7441ee1b8f38cb82fe) fix(action): test CI and fixes for usage with tauri beta-rc ([#114](https://github.com/tauri-apps/tauri-action/pull/114)) on 2021-04-28
|
|
||||||
@@ -1,534 +0,0 @@
|
|||||||
import { platform } from 'os';
|
|
||||||
import { readFileSync, existsSync, copyFileSync, writeFileSync } from 'fs';
|
|
||||||
import { execa } from 'execa';
|
|
||||||
import { parse as parseToml } from '@iarna/toml';
|
|
||||||
import { join, resolve, normalize, sep } from 'path';
|
|
||||||
import { sync as globSync } from 'glob-gitignore';
|
|
||||||
import ignore from 'ignore';
|
|
||||||
import JSON5 from 'json5';
|
|
||||||
|
|
||||||
export function getPackageJson(root: string): any {
|
|
||||||
const packageJsonPath = join(root, 'package.json');
|
|
||||||
if (existsSync(packageJsonPath)) {
|
|
||||||
const packageJsonString = readFileSync(packageJsonPath).toString();
|
|
||||||
const packageJson = JSON.parse(packageJsonString);
|
|
||||||
return packageJson;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTauriDir(root: string): string | null {
|
|
||||||
const ignoreRules = ignore();
|
|
||||||
const gitignorePath = join(root, '.gitignore');
|
|
||||||
if (existsSync(gitignorePath)) {
|
|
||||||
ignoreRules.add(readFileSync(gitignorePath).toString());
|
|
||||||
} else {
|
|
||||||
ignoreRules.add('node_modules').add('target');
|
|
||||||
}
|
|
||||||
const paths = globSync('**/tauri.conf.json', {
|
|
||||||
cwd: root,
|
|
||||||
ignore: ignoreRules,
|
|
||||||
});
|
|
||||||
const tauriConfPath = paths[0];
|
|
||||||
return tauriConfPath ? resolve(root, tauriConfPath, '..') : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getWorkspaceDir(dir: string): string | null {
|
|
||||||
const rootPath = dir;
|
|
||||||
while (dir.length && dir[dir.length - 1] !== sep) {
|
|
||||||
const manifestPath = join(dir, 'Cargo.toml');
|
|
||||||
if (existsSync(manifestPath)) {
|
|
||||||
const toml = parseToml(readFileSync(manifestPath).toString());
|
|
||||||
// @ts-expect-error
|
|
||||||
if (toml.workspace?.members) {
|
|
||||||
// @ts-expect-error
|
|
||||||
const members: string[] = toml.workspace.members;
|
|
||||||
if (members.some((m) => resolve(dir, m) === rootPath)) {
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dir = normalize(join(dir, '..'));
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTargetDir(crateDir: string): string {
|
|
||||||
const def = join(crateDir, 'target');
|
|
||||||
if ('CARGO_TARGET_DIR' in process.env) {
|
|
||||||
return process.env.CARGO_TARGET_DIR ?? def;
|
|
||||||
}
|
|
||||||
let dir = crateDir;
|
|
||||||
while (dir.length && dir[dir.length - 1] !== sep) {
|
|
||||||
let cargoConfigPath = join(dir, '.cargo/config');
|
|
||||||
if (!existsSync(cargoConfigPath)) {
|
|
||||||
cargoConfigPath = join(dir, '.cargo/config.toml');
|
|
||||||
}
|
|
||||||
if (existsSync(cargoConfigPath)) {
|
|
||||||
const cargoConfig = parseToml(readFileSync(cargoConfigPath).toString());
|
|
||||||
// @ts-ignore
|
|
||||||
if (cargoConfig.build?.['target-dir']) {
|
|
||||||
// @ts-ignore
|
|
||||||
return cargoConfig.build['target-dir'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dir = normalize(join(dir, '..'));
|
|
||||||
}
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
|
|
||||||
function hasDependency(dependencyName: string, root: string): boolean {
|
|
||||||
const packageJson = getPackageJson(root);
|
|
||||||
return (
|
|
||||||
packageJson &&
|
|
||||||
(packageJson.dependencies?.[dependencyName] ||
|
|
||||||
packageJson.devDependencies?.[dependencyName])
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function usesYarn(root: string): boolean {
|
|
||||||
return existsSync(join(root, 'yarn.lock'));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function execCommand(
|
|
||||||
command: string,
|
|
||||||
args: string[],
|
|
||||||
{ cwd }: { cwd?: string } = {}
|
|
||||||
): Promise<void> {
|
|
||||||
console.log(`running ${command}`, args);
|
|
||||||
return execa(command, args, {
|
|
||||||
cwd,
|
|
||||||
stdio: 'inherit',
|
|
||||||
env: { FORCE_COLOR: '0' },
|
|
||||||
}).then();
|
|
||||||
}
|
|
||||||
|
|
||||||
interface CargoManifestBin {
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface CargoManifest {
|
|
||||||
package: { version: string; name: string; 'default-run': string };
|
|
||||||
bin: CargoManifestBin[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TauriConfig {
|
|
||||||
package?: {
|
|
||||||
productName?: string;
|
|
||||||
version?: string;
|
|
||||||
};
|
|
||||||
tauri?: {
|
|
||||||
bundle?: {
|
|
||||||
identifier: string;
|
|
||||||
windows?: {
|
|
||||||
wix?: {
|
|
||||||
language?: string | string[] | { [language: string]: unknown };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Application {
|
|
||||||
tauriPath: string;
|
|
||||||
runner: Runner;
|
|
||||||
name: string;
|
|
||||||
version: string;
|
|
||||||
wixLanguage: string | string[] | { [language: string]: unknown };
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BuildOptions {
|
|
||||||
configPath: string | null;
|
|
||||||
distPath: string | null;
|
|
||||||
iconPath: string | null;
|
|
||||||
tauriScript: string | null;
|
|
||||||
args: string[] | null;
|
|
||||||
bundleIdentifier: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Runner {
|
|
||||||
runnerCommand: string;
|
|
||||||
runnerArgs: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Info {
|
|
||||||
tauriPath: string | null;
|
|
||||||
name: string;
|
|
||||||
version: string;
|
|
||||||
wixLanguage: string | string[] | { [language: string]: unknown };
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Artifact {
|
|
||||||
path: string;
|
|
||||||
arch: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _getJson5Config(contents: string): TauriConfig | null {
|
|
||||||
try {
|
|
||||||
const config = JSON5.parse(contents) as TauriConfig;
|
|
||||||
return config;
|
|
||||||
} catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getConfig(path: string): TauriConfig {
|
|
||||||
const contents = readFileSync(path).toString();
|
|
||||||
try {
|
|
||||||
const config = JSON.parse(contents) as TauriConfig;
|
|
||||||
return config;
|
|
||||||
} catch (e) {
|
|
||||||
let json5Conf = _getJson5Config(contents);
|
|
||||||
if (json5Conf === null) {
|
|
||||||
json5Conf = _getJson5Config(
|
|
||||||
readFileSync(join(path, '..', 'tauri.conf.json5')).toString()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (json5Conf) {
|
|
||||||
return json5Conf;
|
|
||||||
}
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getInfo(root: string, inConfigPath: string | null = null): Info {
|
|
||||||
const tauriDir = getTauriDir(root);
|
|
||||||
if (tauriDir !== null) {
|
|
||||||
const configPath = inConfigPath ?? join(tauriDir, 'tauri.conf.json');
|
|
||||||
let name;
|
|
||||||
let version;
|
|
||||||
let wixLanguage: string | string[] | { [language: string]: unknown } =
|
|
||||||
'en-US';
|
|
||||||
const config = getConfig(configPath);
|
|
||||||
if (config.package) {
|
|
||||||
name = config.package.productName;
|
|
||||||
version = config.package.version;
|
|
||||||
if (config.package.version?.endsWith('.json')) {
|
|
||||||
const packageJsonPath = join(tauriDir, config.package.version);
|
|
||||||
const contents = readFileSync(packageJsonPath).toString();
|
|
||||||
version = JSON.parse(contents).version;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!(name && version)) {
|
|
||||||
const manifestPath = join(tauriDir, 'Cargo.toml');
|
|
||||||
const cargoManifest = parseToml(
|
|
||||||
readFileSync(manifestPath).toString()
|
|
||||||
) as any as CargoManifest;
|
|
||||||
name = name || cargoManifest.package.name;
|
|
||||||
version = version || cargoManifest.package.version;
|
|
||||||
}
|
|
||||||
if (config.tauri?.bundle?.windows?.wix?.language) {
|
|
||||||
wixLanguage = config.tauri.bundle.windows.wix.language;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(name && version)) {
|
|
||||||
console.error('Could not determine package name and version');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
tauriPath: tauriDir,
|
|
||||||
name,
|
|
||||||
version,
|
|
||||||
wixLanguage,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
const packageJson = getPackageJson(root);
|
|
||||||
const appName = packageJson
|
|
||||||
? (packageJson.displayName || packageJson.name).replace(/ /g, '-')
|
|
||||||
: 'app';
|
|
||||||
const version = packageJson ? packageJson.version : '0.1.0';
|
|
||||||
return {
|
|
||||||
tauriPath: null,
|
|
||||||
name: appName,
|
|
||||||
version,
|
|
||||||
wixLanguage: 'en-US',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function buildProject(
|
|
||||||
root: string,
|
|
||||||
debug: boolean,
|
|
||||||
{
|
|
||||||
configPath,
|
|
||||||
distPath,
|
|
||||||
iconPath,
|
|
||||||
tauriScript,
|
|
||||||
args,
|
|
||||||
bundleIdentifier,
|
|
||||||
}: BuildOptions
|
|
||||||
): Promise<Artifact[]> {
|
|
||||||
return new Promise<Runner>((resolve, reject) => {
|
|
||||||
if (tauriScript) {
|
|
||||||
const [runnerCommand, ...runnerArgs] = tauriScript.split(' ');
|
|
||||||
resolve({ runnerCommand, runnerArgs });
|
|
||||||
} else if (
|
|
||||||
hasDependency('@tauri-apps/cli', root) ||
|
|
||||||
hasDependency('vue-cli-plugin-tauri', root)
|
|
||||||
) {
|
|
||||||
resolve(
|
|
||||||
usesYarn(root)
|
|
||||||
? { runnerCommand: 'yarn', runnerArgs: ['tauri'] }
|
|
||||||
: { runnerCommand: 'npx', runnerArgs: ['tauri'] }
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
execCommand('npm', ['install', '-g', '@tauri-apps/cli'], {
|
|
||||||
cwd: undefined,
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
resolve({ runnerCommand: 'tauri', runnerArgs: [] });
|
|
||||||
})
|
|
||||||
.catch(reject);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((runner: Runner) => {
|
|
||||||
const info = getInfo(root, configPath);
|
|
||||||
if (info.tauriPath) {
|
|
||||||
return {
|
|
||||||
tauriPath: info.tauriPath,
|
|
||||||
runner,
|
|
||||||
name: info.name,
|
|
||||||
version: info.version,
|
|
||||||
wixLanguage: info.wixLanguage,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
const packageJson = getPackageJson(root);
|
|
||||||
return execCommand(
|
|
||||||
runner.runnerCommand,
|
|
||||||
[...runner.runnerArgs, 'init', '--ci', '--app-name', info.name],
|
|
||||||
{
|
|
||||||
cwd: root,
|
|
||||||
}
|
|
||||||
).then(() => {
|
|
||||||
const tauriPath = getTauriDir(root);
|
|
||||||
if (tauriPath === null) {
|
|
||||||
console.error('Failed to resolve Tauri path');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
const configPath = join(tauriPath, 'tauri.conf.json');
|
|
||||||
const config = getConfig(configPath);
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`Replacing tauri.conf.json config - package.version=${info.version}`
|
|
||||||
);
|
|
||||||
const pkgConfig = {
|
|
||||||
...config.package,
|
|
||||||
version: info.version,
|
|
||||||
};
|
|
||||||
if (packageJson?.productName) {
|
|
||||||
console.log(
|
|
||||||
`Replacing tauri.conf.json config - package.productName=${packageJson.productName}`
|
|
||||||
);
|
|
||||||
pkgConfig.productName = packageJson.productName;
|
|
||||||
}
|
|
||||||
config.package = pkgConfig;
|
|
||||||
|
|
||||||
if (bundleIdentifier) {
|
|
||||||
console.log(
|
|
||||||
`Replacing tauri.conf.json config - tauri.bundle.identifier=${bundleIdentifier}`
|
|
||||||
);
|
|
||||||
config.tauri = {
|
|
||||||
...config.tauri,
|
|
||||||
bundle: {
|
|
||||||
...config.tauri?.bundle,
|
|
||||||
identifier: bundleIdentifier,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
||||||
|
|
||||||
const app = {
|
|
||||||
tauriPath,
|
|
||||||
runner,
|
|
||||||
name: info.name,
|
|
||||||
version: info.version,
|
|
||||||
wixLanguage: info.wixLanguage,
|
|
||||||
};
|
|
||||||
if (iconPath) {
|
|
||||||
return execCommand(
|
|
||||||
runner.runnerCommand,
|
|
||||||
[...runner.runnerArgs, 'icon', join(root, iconPath)],
|
|
||||||
{
|
|
||||||
cwd: root,
|
|
||||||
}
|
|
||||||
).then(() => app);
|
|
||||||
}
|
|
||||||
|
|
||||||
return app;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((app: Application) => {
|
|
||||||
const tauriConfPath = join(app.tauriPath, 'tauri.conf.json');
|
|
||||||
if (configPath !== null) {
|
|
||||||
copyFileSync(configPath, tauriConfPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (distPath) {
|
|
||||||
const tauriConf = JSON.parse(readFileSync(tauriConfPath).toString());
|
|
||||||
tauriConf.build.distDir = distPath;
|
|
||||||
writeFileSync(tauriConfPath, JSON.stringify(tauriConf));
|
|
||||||
}
|
|
||||||
|
|
||||||
const tauriArgs = debug ? ['--debug', ...(args ?? [])] : args ?? [];
|
|
||||||
let buildCommand;
|
|
||||||
let buildArgs: string[] = [];
|
|
||||||
|
|
||||||
if (hasDependency('vue-cli-plugin-tauri', root)) {
|
|
||||||
if (usesYarn(root)) {
|
|
||||||
buildCommand = 'yarn';
|
|
||||||
buildArgs = ['tauri:build'];
|
|
||||||
} else {
|
|
||||||
buildCommand = 'npm';
|
|
||||||
buildArgs = ['run', 'tauri:build'];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
buildCommand = app.runner.runnerCommand;
|
|
||||||
buildArgs = [...app.runner.runnerArgs, 'build'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return execCommand(buildCommand, [...buildArgs, ...tauriArgs], {
|
|
||||||
cwd: root,
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
let fileAppName = app.name;
|
|
||||||
// on Linux, the app product name is converted to kebab-case
|
|
||||||
if (!['darwin', 'win32'].includes(platform())) {
|
|
||||||
fileAppName = fileAppName
|
|
||||||
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
||||||
.replace(/([A-Z])([A-Z])(?=[a-z])/g, '$1-$2')
|
|
||||||
.replace(/[ _.]/g, '-')
|
|
||||||
.toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
const cratePath = getWorkspaceDir(app.tauriPath) ?? app.tauriPath;
|
|
||||||
|
|
||||||
const found = [...tauriArgs].findIndex(
|
|
||||||
(e) => e === '-t' || e === '--target'
|
|
||||||
);
|
|
||||||
const targetPath = found >= 0 ? [...tauriArgs][found + 1] : '';
|
|
||||||
|
|
||||||
const artifactsPath = join(
|
|
||||||
getTargetDir(cratePath),
|
|
||||||
targetPath,
|
|
||||||
debug ? 'debug' : 'release'
|
|
||||||
);
|
|
||||||
|
|
||||||
let arch =
|
|
||||||
targetPath.search('-') >= 0
|
|
||||||
? targetPath.split('-')[0]
|
|
||||||
: process.arch;
|
|
||||||
|
|
||||||
if (platform() === 'darwin') {
|
|
||||||
if (arch === 'x86_64') {
|
|
||||||
arch = 'x64';
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
join(
|
|
||||||
artifactsPath,
|
|
||||||
`bundle/dmg/${fileAppName}_${app.version}_${arch}.dmg`
|
|
||||||
),
|
|
||||||
join(artifactsPath, `bundle/macos/${fileAppName}.app`),
|
|
||||||
join(artifactsPath, `bundle/macos/${fileAppName}.app.tar.gz`),
|
|
||||||
join(artifactsPath, `bundle/macos/${fileAppName}.app.tar.gz.sig`),
|
|
||||||
].map((path) => ({ path, arch }));
|
|
||||||
} else if (platform() === 'win32') {
|
|
||||||
arch = arch.startsWith('i') ? 'x86' : 'x64';
|
|
||||||
|
|
||||||
// If multiple Wix languages are specified, multiple installers (.msi) will be made
|
|
||||||
// The .zip and .sig are only generated for the first specified language
|
|
||||||
let langs;
|
|
||||||
if (typeof app.wixLanguage === 'string') {
|
|
||||||
langs = [app.wixLanguage];
|
|
||||||
} else if (Array.isArray(app.wixLanguage)) {
|
|
||||||
langs = app.wixLanguage;
|
|
||||||
} else {
|
|
||||||
langs = Object.keys(app.wixLanguage);
|
|
||||||
}
|
|
||||||
const artifacts: string[] = [];
|
|
||||||
langs.forEach((lang) => {
|
|
||||||
artifacts.push(
|
|
||||||
join(
|
|
||||||
artifactsPath,
|
|
||||||
`bundle/msi/${fileAppName}_${app.version}_${arch}_${lang}.msi`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
artifacts.push(
|
|
||||||
join(
|
|
||||||
artifactsPath,
|
|
||||||
`bundle/msi/${fileAppName}_${app.version}_${arch}_${lang}.msi.zip`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
artifacts.push(
|
|
||||||
join(
|
|
||||||
artifactsPath,
|
|
||||||
`bundle/msi/${fileAppName}_${app.version}_${arch}_${lang}.msi.zip.sig`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
return artifacts.map((path) => ({ path, arch }));
|
|
||||||
} else {
|
|
||||||
const debianArch =
|
|
||||||
arch === 'x64' || arch === 'x86_64'
|
|
||||||
? 'amd64'
|
|
||||||
: arch === 'x32' || arch === 'i686'
|
|
||||||
? 'i386'
|
|
||||||
: arch === 'arm'
|
|
||||||
? 'armhf'
|
|
||||||
: arch === 'aarch64'
|
|
||||||
? 'arm64'
|
|
||||||
: arch;
|
|
||||||
const appImageArch =
|
|
||||||
arch === 'x64' || arch === 'x86_64'
|
|
||||||
? 'amd64'
|
|
||||||
: arch === 'x32' || arch === 'i686'
|
|
||||||
? 'i386'
|
|
||||||
: arch;
|
|
||||||
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
path: join(
|
|
||||||
artifactsPath,
|
|
||||||
`bundle/deb/${fileAppName}_${app.version}_${debianArch}.deb`
|
|
||||||
),
|
|
||||||
arch: debianArch,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: join(
|
|
||||||
artifactsPath,
|
|
||||||
`bundle/appimage/${fileAppName}_${app.version}_${appImageArch}.AppImage`
|
|
||||||
),
|
|
||||||
arch: appImageArch,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: join(
|
|
||||||
artifactsPath,
|
|
||||||
`bundle/appimage/${fileAppName}_${app.version}_${appImageArch}.AppImage.tar.gz`
|
|
||||||
),
|
|
||||||
arch: appImageArch,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: join(
|
|
||||||
artifactsPath,
|
|
||||||
`bundle/appimage/${fileAppName}_${app.version}_${appImageArch}.AppImage.tar.gz.sig`
|
|
||||||
),
|
|
||||||
arch: appImageArch,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((artifacts) => {
|
|
||||||
console.log(
|
|
||||||
`Expected artifacts paths:\n${artifacts
|
|
||||||
.map((a) => a.path)
|
|
||||||
.join('\n')}`
|
|
||||||
);
|
|
||||||
return artifacts.filter((p) => existsSync(p.path));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@tauri-apps/action-core",
|
|
||||||
"version": "0.3.1",
|
|
||||||
"author": "Lucas Nogueira <lucas@tauri.studio>",
|
|
||||||
"license": "MIT",
|
|
||||||
"main": "dist",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"build": "rollup --config",
|
|
||||||
"prepublishOnly": "rollup --config"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@iarna/toml": "2.2.5",
|
|
||||||
"execa": "6.1.0",
|
|
||||||
"glob-gitignore": "^1.0.14",
|
|
||||||
"ignore": "^5.2.0",
|
|
||||||
"json5": "^2.2.2",
|
|
||||||
"tslib": "2.4.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@rollup/plugin-typescript": "10.0.1",
|
|
||||||
"@types/node": "16.18.11",
|
|
||||||
"rollup": "2.79.1",
|
|
||||||
"typescript": "4.9.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 12.20.0",
|
|
||||||
"npm": ">= 6.6.0",
|
|
||||||
"yarn": ">= 1.19.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import typescript from '@rollup/plugin-typescript';
|
|
||||||
import pkg from './package.json';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
treeshake: true,
|
|
||||||
perf: true,
|
|
||||||
input: { index: 'index.ts' },
|
|
||||||
output: {
|
|
||||||
dir: 'dist',
|
|
||||||
format: 'esm',
|
|
||||||
entryFileNames: '[name].js',
|
|
||||||
exports: 'named',
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
typescript({
|
|
||||||
tsconfig: './tsconfig.json',
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
external: [...Object.keys(pkg.dependencies || {}), 'path'],
|
|
||||||
watch: {
|
|
||||||
chokidar: true,
|
|
||||||
include: 'src/**',
|
|
||||||
exclude: 'node_modules/**',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"declaration": true,
|
|
||||||
"outDir": "./dist",
|
|
||||||
"rootDir": ".",
|
|
||||||
"allowSyntheticDefaultImports": true
|
|
||||||
},
|
|
||||||
"include": ["index.ts", "index.d.ts"]
|
|
||||||
}
|
|
||||||
2621
pnpm-lock.yaml
generated
Normal file
233
src/build.ts
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
import { platform } from 'os';
|
||||||
|
import { readFileSync, existsSync, copyFileSync, writeFileSync } from 'fs';
|
||||||
|
import { join } from 'path';
|
||||||
|
|
||||||
|
import { initProject } from './init-project';
|
||||||
|
import {
|
||||||
|
execCommand,
|
||||||
|
getInfo,
|
||||||
|
getTargetDir,
|
||||||
|
getWorkspaceDir,
|
||||||
|
hasDependency,
|
||||||
|
usesPnpm,
|
||||||
|
usesYarn,
|
||||||
|
} from './utils';
|
||||||
|
|
||||||
|
import type { Artifact, BuildOptions, Runner } from './types';
|
||||||
|
|
||||||
|
async function getRunner(
|
||||||
|
root: string,
|
||||||
|
tauriScript: string | null
|
||||||
|
): Promise<Runner> {
|
||||||
|
if (tauriScript) {
|
||||||
|
const [runnerCommand, ...runnerArgs] = tauriScript.split(' ');
|
||||||
|
return { runnerCommand, runnerArgs };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
hasDependency('@tauri-apps/cli', root) ||
|
||||||
|
hasDependency('vue-cli-plugin-tauri', root)
|
||||||
|
) {
|
||||||
|
if (usesYarn(root)) return { runnerCommand: 'yarn', runnerArgs: ['tauri'] };
|
||||||
|
if (usesPnpm(root)) return { runnerCommand: 'pnpm', runnerArgs: ['tauri'] };
|
||||||
|
// FIXME: This can trigger a download of the tauri alpha package. Likely when the tauri frontend is part of a workspace and projectPath is undefined.
|
||||||
|
return { runnerCommand: 'npx', runnerArgs: ['tauri'] };
|
||||||
|
}
|
||||||
|
|
||||||
|
await execCommand('npm', ['install', '-g', '@tauri-apps/cli'], {
|
||||||
|
cwd: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
return { runnerCommand: 'tauri', runnerArgs: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function buildProject(
|
||||||
|
root: string,
|
||||||
|
debug: boolean,
|
||||||
|
buildOpts: BuildOptions
|
||||||
|
): Promise<Artifact[]> {
|
||||||
|
const runner = await getRunner(root, buildOpts.tauriScript);
|
||||||
|
|
||||||
|
const info = getInfo(root, buildOpts.configPath);
|
||||||
|
|
||||||
|
const app = info.tauriPath
|
||||||
|
? {
|
||||||
|
tauriPath: info.tauriPath,
|
||||||
|
runner,
|
||||||
|
name: info.name,
|
||||||
|
version: info.version,
|
||||||
|
wixLanguage: info.wixLanguage,
|
||||||
|
}
|
||||||
|
: await initProject(root, runner, info, buildOpts);
|
||||||
|
|
||||||
|
const tauriConfPath = join(app.tauriPath, 'tauri.conf.json');
|
||||||
|
if (buildOpts.configPath !== null) {
|
||||||
|
copyFileSync(buildOpts.configPath, tauriConfPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buildOpts.distPath) {
|
||||||
|
const tauriConf = JSON.parse(readFileSync(tauriConfPath).toString());
|
||||||
|
tauriConf.build.distDir = buildOpts.distPath;
|
||||||
|
writeFileSync(tauriConfPath, JSON.stringify(tauriConf));
|
||||||
|
}
|
||||||
|
|
||||||
|
const tauriArgs = debug
|
||||||
|
? ['--debug', ...(buildOpts.args ?? [])]
|
||||||
|
: buildOpts.args ?? [];
|
||||||
|
let buildCommand;
|
||||||
|
let buildArgs: string[] = [];
|
||||||
|
|
||||||
|
if (hasDependency('vue-cli-plugin-tauri', root)) {
|
||||||
|
if (usesYarn(root)) {
|
||||||
|
buildCommand = 'yarn';
|
||||||
|
buildArgs = ['tauri:build'];
|
||||||
|
}
|
||||||
|
if (usesPnpm(root)) {
|
||||||
|
buildCommand = 'pnpm';
|
||||||
|
buildArgs = ['tauri:build'];
|
||||||
|
} else {
|
||||||
|
buildCommand = 'npm';
|
||||||
|
buildArgs = ['run', 'tauri:build'];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buildCommand = app.runner.runnerCommand;
|
||||||
|
buildArgs = [...app.runner.runnerArgs, 'build'];
|
||||||
|
}
|
||||||
|
|
||||||
|
await execCommand(buildCommand, [...buildArgs, ...tauriArgs], {
|
||||||
|
cwd: root,
|
||||||
|
});
|
||||||
|
|
||||||
|
let fileAppName = app.name;
|
||||||
|
// on Linux, the app product name is converted to kebab-case
|
||||||
|
if (!['darwin', 'win32'].includes(platform())) {
|
||||||
|
fileAppName = fileAppName
|
||||||
|
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
||||||
|
.replace(/([A-Z])([A-Z])(?=[a-z])/g, '$1-$2')
|
||||||
|
.replace(/[ _.]/g, '-')
|
||||||
|
.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
const cratePath = getWorkspaceDir(app.tauriPath) ?? app.tauriPath;
|
||||||
|
|
||||||
|
const found = [...tauriArgs].findIndex((e) => e === '-t' || e === '--target');
|
||||||
|
const targetPath = found >= 0 ? [...tauriArgs][found + 1] : '';
|
||||||
|
|
||||||
|
const artifactsPath = join(
|
||||||
|
getTargetDir(cratePath),
|
||||||
|
targetPath,
|
||||||
|
debug ? 'debug' : 'release'
|
||||||
|
);
|
||||||
|
|
||||||
|
let arch =
|
||||||
|
targetPath.search('-') >= 0 ? targetPath.split('-')[0] : process.arch;
|
||||||
|
|
||||||
|
let artifacts: Artifact[] = [];
|
||||||
|
|
||||||
|
if (platform() === 'darwin') {
|
||||||
|
if (arch === 'x86_64') {
|
||||||
|
arch = 'x64';
|
||||||
|
}
|
||||||
|
|
||||||
|
artifacts = [
|
||||||
|
join(
|
||||||
|
artifactsPath,
|
||||||
|
`bundle/dmg/${fileAppName}_${app.version}_${arch}.dmg`
|
||||||
|
),
|
||||||
|
join(artifactsPath, `bundle/macos/${fileAppName}.app`),
|
||||||
|
join(artifactsPath, `bundle/macos/${fileAppName}.app.tar.gz`),
|
||||||
|
join(artifactsPath, `bundle/macos/${fileAppName}.app.tar.gz.sig`),
|
||||||
|
].map((path) => ({ path, arch }));
|
||||||
|
} else if (platform() === 'win32') {
|
||||||
|
arch = arch.startsWith('i') ? 'x86' : 'x64';
|
||||||
|
|
||||||
|
// If multiple Wix languages are specified, multiple installers (.msi) will be made
|
||||||
|
// The .zip and .sig are only generated for the first specified language
|
||||||
|
let langs;
|
||||||
|
if (typeof app.wixLanguage === 'string') {
|
||||||
|
langs = [app.wixLanguage];
|
||||||
|
} else if (Array.isArray(app.wixLanguage)) {
|
||||||
|
langs = app.wixLanguage;
|
||||||
|
} else {
|
||||||
|
langs = Object.keys(app.wixLanguage);
|
||||||
|
}
|
||||||
|
|
||||||
|
const winArtifacts: string[] = [];
|
||||||
|
|
||||||
|
langs.forEach((lang) => {
|
||||||
|
winArtifacts.push(
|
||||||
|
join(
|
||||||
|
artifactsPath,
|
||||||
|
`bundle/msi/${fileAppName}_${app.version}_${arch}_${lang}.msi`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
winArtifacts.push(
|
||||||
|
join(
|
||||||
|
artifactsPath,
|
||||||
|
`bundle/msi/${fileAppName}_${app.version}_${arch}_${lang}.msi.zip`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
winArtifacts.push(
|
||||||
|
join(
|
||||||
|
artifactsPath,
|
||||||
|
`bundle/msi/${fileAppName}_${app.version}_${arch}_${lang}.msi.zip.sig`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
artifacts = winArtifacts.map((path) => ({ path, arch }));
|
||||||
|
} else {
|
||||||
|
const debianArch =
|
||||||
|
arch === 'x64' || arch === 'x86_64'
|
||||||
|
? 'amd64'
|
||||||
|
: arch === 'x32' || arch === 'i686'
|
||||||
|
? 'i386'
|
||||||
|
: arch === 'arm'
|
||||||
|
? 'armhf'
|
||||||
|
: arch === 'aarch64'
|
||||||
|
? 'arm64'
|
||||||
|
: arch;
|
||||||
|
const appImageArch =
|
||||||
|
arch === 'x64' || arch === 'x86_64'
|
||||||
|
? 'amd64'
|
||||||
|
: arch === 'x32' || arch === 'i686'
|
||||||
|
? 'i386'
|
||||||
|
: arch;
|
||||||
|
|
||||||
|
artifacts = [
|
||||||
|
{
|
||||||
|
path: join(
|
||||||
|
artifactsPath,
|
||||||
|
`bundle/deb/${fileAppName}_${app.version}_${debianArch}.deb`
|
||||||
|
),
|
||||||
|
arch: debianArch,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: join(
|
||||||
|
artifactsPath,
|
||||||
|
`bundle/appimage/${fileAppName}_${app.version}_${appImageArch}.AppImage`
|
||||||
|
),
|
||||||
|
arch: appImageArch,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: join(
|
||||||
|
artifactsPath,
|
||||||
|
`bundle/appimage/${fileAppName}_${app.version}_${appImageArch}.AppImage.tar.gz`
|
||||||
|
),
|
||||||
|
arch: appImageArch,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: join(
|
||||||
|
artifactsPath,
|
||||||
|
`bundle/appimage/${fileAppName}_${app.version}_${appImageArch}.AppImage.tar.gz.sig`
|
||||||
|
),
|
||||||
|
arch: appImageArch,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`Expected artifacts paths:\n${artifacts.map((a) => a.path).join('\n')}`
|
||||||
|
);
|
||||||
|
return artifacts.filter((p) => existsSync(p.path));
|
||||||
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
|
import fs from 'fs';
|
||||||
|
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import { getOctokit, context } from '@actions/github';
|
import { getOctokit, context } from '@actions/github';
|
||||||
import { GitHub } from '@actions/github/lib/utils';
|
import { GitHub } from '@actions/github/lib/utils';
|
||||||
import fs from 'fs';
|
|
||||||
|
|
||||||
interface Release {
|
interface Release {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -25,7 +26,7 @@ function allReleases(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function createRelease(
|
export async function createRelease(
|
||||||
tagName: string,
|
tagName: string,
|
||||||
releaseName: string,
|
releaseName: string,
|
||||||
body?: string,
|
body?: string,
|
||||||
@@ -44,11 +45,12 @@ export default async function createRelease(
|
|||||||
const { owner, repo } = context.repo;
|
const { owner, repo } = context.repo;
|
||||||
|
|
||||||
const bodyPath = core.getInput('body_path', { required: false });
|
const bodyPath = core.getInput('body_path', { required: false });
|
||||||
let bodyFileContent = null;
|
let bodyFileContent: string | null = null;
|
||||||
if (bodyPath !== '' && !!bodyPath) {
|
if (bodyPath !== '' && !!bodyPath) {
|
||||||
try {
|
try {
|
||||||
bodyFileContent = fs.readFileSync(bodyPath, { encoding: 'utf8' });
|
bodyFileContent = fs.readFileSync(bodyPath, { encoding: 'utf8' });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
//@ts-ignore
|
||||||
core.setFailed(error.message);
|
core.setFailed(error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,7 +62,7 @@ export default async function createRelease(
|
|||||||
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)) {
|
for await (const response of allReleases(github)) {
|
||||||
let releaseWithTag = response.data.find(
|
const releaseWithTag = response.data.find(
|
||||||
(release) => release.tag_name === tagName
|
(release) => release.tag_name === tagName
|
||||||
);
|
);
|
||||||
if (releaseWithTag) {
|
if (releaseWithTag) {
|
||||||
@@ -84,6 +86,7 @@ export default async function createRelease(
|
|||||||
console.log(`Found release with tag ${tagName}.`);
|
console.log(`Found release with tag ${tagName}.`);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// @ts-ignore
|
||||||
if (error.status === 404 || error.message === 'release not found') {
|
if (error.status === 404 || error.message === 'release not found') {
|
||||||
console.log(`Couldn't find release with tag ${tagName}. Creating one.`);
|
console.log(`Couldn't find release with tag ${tagName}. Creating one.`);
|
||||||
const createdRelease = await github.rest.repos.createRelease({
|
const createdRelease = await github.rest.repos.createRelease({
|
||||||
@@ -1,19 +1,18 @@
|
|||||||
import { platform } from 'os';
|
|
||||||
import * as core from '@actions/core';
|
|
||||||
import { join, resolve, dirname, basename } from 'path';
|
|
||||||
import { existsSync } from 'fs';
|
import { existsSync } from 'fs';
|
||||||
import uploadReleaseAssets from './upload-release-assets';
|
import { platform } from 'os';
|
||||||
import uploadVersionJSON from './upload-version-json';
|
import { join, resolve, dirname, basename } from 'path';
|
||||||
import createRelease from './create-release';
|
|
||||||
import {
|
import * as core from '@actions/core';
|
||||||
getPackageJson,
|
|
||||||
buildProject,
|
|
||||||
getInfo,
|
|
||||||
execCommand,
|
|
||||||
} from '@tauri-apps/action-core';
|
|
||||||
import type { BuildOptions } from '@tauri-apps/action-core';
|
|
||||||
import stringArgv from 'string-argv';
|
import stringArgv from 'string-argv';
|
||||||
|
|
||||||
|
import { createRelease } from './create-release';
|
||||||
|
import { uploadAssets as uploadReleaseAssets } from './upload-release-assets';
|
||||||
|
import { uploadVersionJSON } from './upload-version-json';
|
||||||
|
import { buildProject } from './build';
|
||||||
|
import { execCommand, getInfo, getPackageJson } from './utils';
|
||||||
|
|
||||||
|
import type { BuildOptions } from './types';
|
||||||
|
|
||||||
async function run(): Promise<void> {
|
async function run(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const projectPath = resolve(
|
const projectPath = resolve(
|
||||||
@@ -137,6 +136,7 @@ async function run(): Promise<void> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// @ts-ignore
|
||||||
core.setFailed(error.message);
|
core.setFailed(error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
81
src/init-project.ts
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import { writeFileSync } from 'fs';
|
||||||
|
import { join } from 'path';
|
||||||
|
|
||||||
|
import { execCommand, getConfig, getPackageJson, getTauriDir } from './utils';
|
||||||
|
|
||||||
|
import type { Application, BuildOptions, Info, Runner } from './types';
|
||||||
|
|
||||||
|
export async function initProject(
|
||||||
|
root: string,
|
||||||
|
runner: Runner,
|
||||||
|
info: Info,
|
||||||
|
{ iconPath, bundleIdentifier }: BuildOptions
|
||||||
|
): Promise<Application> {
|
||||||
|
const packageJson = getPackageJson(root);
|
||||||
|
const tauriPath = getTauriDir(root);
|
||||||
|
|
||||||
|
await execCommand(
|
||||||
|
runner.runnerCommand,
|
||||||
|
[...runner.runnerArgs, 'init', '--ci', '--app-name', info.name],
|
||||||
|
{
|
||||||
|
cwd: root,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (tauriPath === null) {
|
||||||
|
console.error('Failed to resolve Tauri path');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
const configPath = join(tauriPath, 'tauri.conf.json');
|
||||||
|
const config = getConfig(configPath);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`Replacing tauri.conf.json config - package.version=${info.version}`
|
||||||
|
);
|
||||||
|
const pkgConfig = {
|
||||||
|
...config.package,
|
||||||
|
version: info.version,
|
||||||
|
};
|
||||||
|
if (packageJson?.productName) {
|
||||||
|
console.log(
|
||||||
|
`Replacing tauri.conf.json config - package.productName=${packageJson.productName}`
|
||||||
|
);
|
||||||
|
pkgConfig.productName = packageJson.productName;
|
||||||
|
}
|
||||||
|
config.package = pkgConfig;
|
||||||
|
|
||||||
|
if (bundleIdentifier) {
|
||||||
|
console.log(
|
||||||
|
`Replacing tauri.conf.json config - tauri.bundle.identifier=${bundleIdentifier}`
|
||||||
|
);
|
||||||
|
config.tauri = {
|
||||||
|
...config.tauri,
|
||||||
|
bundle: {
|
||||||
|
...config.tauri?.bundle,
|
||||||
|
identifier: bundleIdentifier,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
writeFileSync(configPath, JSON.stringify(config, null, 2));
|
||||||
|
|
||||||
|
const app = {
|
||||||
|
tauriPath,
|
||||||
|
runner,
|
||||||
|
name: info.name,
|
||||||
|
version: info.version,
|
||||||
|
wixLanguage: info.wixLanguage,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (iconPath) {
|
||||||
|
await execCommand(
|
||||||
|
runner.runnerCommand,
|
||||||
|
[...runner.runnerArgs, 'icon', join(root, iconPath)],
|
||||||
|
{
|
||||||
|
cwd: root,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return app;
|
||||||
|
}
|
||||||
59
src/types.d.ts
vendored
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
export interface Application {
|
||||||
|
tauriPath: string;
|
||||||
|
runner: Runner;
|
||||||
|
name: string;
|
||||||
|
version: string;
|
||||||
|
wixLanguage: string | string[] | { [language: string]: unknown };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Artifact {
|
||||||
|
path: string;
|
||||||
|
arch: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BuildOptions {
|
||||||
|
configPath: string | null;
|
||||||
|
distPath: string | null;
|
||||||
|
iconPath: string | null;
|
||||||
|
tauriScript: string | null;
|
||||||
|
args: string[] | null;
|
||||||
|
bundleIdentifier: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CargoManifestBin {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CargoManifest {
|
||||||
|
package: { version: string; name: string; 'default-run': string };
|
||||||
|
bin: CargoManifestBin[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Info {
|
||||||
|
tauriPath: string | null;
|
||||||
|
name: string;
|
||||||
|
version: string;
|
||||||
|
wixLanguage: string | string[] | { [language: string]: unknown };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Runner {
|
||||||
|
runnerCommand: string;
|
||||||
|
runnerArgs: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TauriConfig {
|
||||||
|
package?: {
|
||||||
|
productName?: string;
|
||||||
|
version?: string;
|
||||||
|
};
|
||||||
|
tauri?: {
|
||||||
|
bundle?: {
|
||||||
|
identifier: string;
|
||||||
|
windows?: {
|
||||||
|
wix?: {
|
||||||
|
language?: string | string[] | { [language: string]: unknown };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
import { getOctokit, context } from '@actions/github';
|
|
||||||
import { Artifact } from '@tauri-apps/action-core';
|
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { getAssetName } from './utils';
|
|
||||||
|
|
||||||
export default async function uploadAssets(
|
import { getOctokit, context } from '@actions/github';
|
||||||
releaseId: number,
|
|
||||||
assets: Artifact[]
|
import { getAssetName } from './utils';
|
||||||
) {
|
import type { Artifact } from './types';
|
||||||
|
|
||||||
|
export async function uploadAssets(releaseId: number, assets: Artifact[]) {
|
||||||
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');
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,29 @@
|
|||||||
import { getOctokit, context } from '@actions/github';
|
|
||||||
import { resolve } from 'path';
|
|
||||||
import { readFileSync, writeFileSync } from 'fs';
|
import { readFileSync, writeFileSync } from 'fs';
|
||||||
import uploadAssets from './upload-release-assets';
|
import { platform } from 'os';
|
||||||
import fetch from 'node-fetch';
|
import { resolve } from 'path';
|
||||||
import { arch, platform } from 'os';
|
|
||||||
import { getAssetName } from './utils';
|
|
||||||
import { Artifact } from '@tauri-apps/action-core';
|
|
||||||
|
|
||||||
export default async function uploadVersionJSON({
|
import { getOctokit, context } from '@actions/github';
|
||||||
|
|
||||||
|
import { uploadAssets } from './upload-release-assets';
|
||||||
|
import { getAssetName } from './utils';
|
||||||
|
|
||||||
|
import type { Artifact } from './types';
|
||||||
|
|
||||||
|
type Platform = {
|
||||||
|
signature: string;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type VersionContent = {
|
||||||
|
version: string;
|
||||||
|
notes: string;
|
||||||
|
pub_date: string;
|
||||||
|
platforms: {
|
||||||
|
[key: string]: Platform;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function uploadVersionJSON({
|
||||||
version,
|
version,
|
||||||
notes,
|
notes,
|
||||||
tagName,
|
tagName,
|
||||||
@@ -28,7 +44,7 @@ export default async function uploadVersionJSON({
|
|||||||
|
|
||||||
const versionFilename = 'latest.json';
|
const versionFilename = 'latest.json';
|
||||||
const versionFile = resolve(process.cwd(), versionFilename);
|
const versionFile = resolve(process.cwd(), versionFilename);
|
||||||
const versionContent = {
|
const versionContent: VersionContent = {
|
||||||
version,
|
version,
|
||||||
notes,
|
notes,
|
||||||
pub_date: new Date().toISOString(),
|
pub_date: new Date().toISOString(),
|
||||||
@@ -56,7 +72,7 @@ export default async function uploadVersionJSON({
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
).data as any as ArrayBuffer;
|
).data as unknown as ArrayBuffer;
|
||||||
|
|
||||||
versionContent.platforms = JSON.parse(
|
versionContent.platforms = JSON.parse(
|
||||||
Buffer.from(assetData).toString()
|
Buffer.from(assetData).toString()
|
||||||
@@ -81,7 +97,7 @@ export default async function uploadVersionJSON({
|
|||||||
|
|
||||||
// Untagged release downloads won't work after the release was published
|
// Untagged release downloads won't work after the release was published
|
||||||
downloadUrl = downloadUrl?.replace(
|
downloadUrl = downloadUrl?.replace(
|
||||||
/\/download\/(untagged-[^\/]+)\//,
|
/\/download\/(untagged-[^/]+)\//,
|
||||||
tagName ? `/download/${tagName}/` : '/latest/download/'
|
tagName ? `/download/${tagName}/` : '/latest/download/'
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -104,7 +120,7 @@ export default async function uploadVersionJSON({
|
|||||||
: arch;
|
: arch;
|
||||||
|
|
||||||
// https://github.com/tauri-apps/tauri/blob/fd125f76d768099dc3d4b2d4114349ffc31ffac9/core/tauri/src/updater/core.rs#L856
|
// https://github.com/tauri-apps/tauri/blob/fd125f76d768099dc3d4b2d4114349ffc31ffac9/core/tauri/src/updater/core.rs#L856
|
||||||
versionContent.platforms[`${os}-${arch}`] = {
|
(versionContent.platforms[`${os}-${arch}`] as unknown) = {
|
||||||
signature: readFileSync(sigFile.path).toString(),
|
signature: readFileSync(sigFile.path).toString(),
|
||||||
url: downloadUrl,
|
url: downloadUrl,
|
||||||
};
|
};
|
||||||
235
src/utils.ts
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
import { existsSync, readFileSync } from 'fs';
|
||||||
|
import path, { join, normalize, resolve, sep } from 'path';
|
||||||
|
|
||||||
|
import { execa } from 'execa';
|
||||||
|
import { parse as parseToml } from '@iarna/toml';
|
||||||
|
import { sync as globSync } from 'glob-gitignore';
|
||||||
|
import ignore from 'ignore';
|
||||||
|
import JSON5 from 'json5';
|
||||||
|
|
||||||
|
import type { CargoManifest, Info, TauriConfig } from './types';
|
||||||
|
|
||||||
|
/*** constants ***/
|
||||||
|
export const extensions = [
|
||||||
|
'.app.tar.gz.sig',
|
||||||
|
'.app.tar.gz',
|
||||||
|
'.dmg',
|
||||||
|
'.AppImage.tar.gz.sig',
|
||||||
|
'.AppImage.tar.gz',
|
||||||
|
'.AppImage',
|
||||||
|
'.deb',
|
||||||
|
'.msi.zip.sig',
|
||||||
|
'.msi.zip',
|
||||||
|
'.msi',
|
||||||
|
];
|
||||||
|
|
||||||
|
/*** helper functions ***/
|
||||||
|
export function getAssetName(assetPath: string) {
|
||||||
|
const basename = path.basename(assetPath);
|
||||||
|
const exts = extensions.filter((s) => basename.includes(s));
|
||||||
|
const ext = exts[0] || path.extname(assetPath);
|
||||||
|
const filename = basename.replace(ext, '');
|
||||||
|
|
||||||
|
let arch = '';
|
||||||
|
if (ext === '.app.tar.gz.sig' || ext === '.app.tar.gz') {
|
||||||
|
arch = assetPath.includes('universal-apple-darwin')
|
||||||
|
? '_universal'
|
||||||
|
: assetPath.includes('aarch64-apple-darwin')
|
||||||
|
? '_aarch64'
|
||||||
|
: '_x64';
|
||||||
|
}
|
||||||
|
|
||||||
|
return assetPath.includes(`${path.sep}debug${path.sep}`)
|
||||||
|
? `${filename}-debug${arch}${ext}`
|
||||||
|
: `${filename}${arch}${ext}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPackageJson(root: string) {
|
||||||
|
const packageJsonPath = join(root, 'package.json');
|
||||||
|
if (existsSync(packageJsonPath)) {
|
||||||
|
const packageJsonString = readFileSync(packageJsonPath).toString();
|
||||||
|
const packageJson = JSON.parse(packageJsonString);
|
||||||
|
return packageJson;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTauriDir(root: string): string | null {
|
||||||
|
const ignoreRules = ignore();
|
||||||
|
const gitignorePath = join(root, '.gitignore');
|
||||||
|
if (existsSync(gitignorePath)) {
|
||||||
|
ignoreRules.add(readFileSync(gitignorePath).toString());
|
||||||
|
} else {
|
||||||
|
ignoreRules.add('node_modules').add('target');
|
||||||
|
}
|
||||||
|
const paths = globSync('**/tauri.conf.json', {
|
||||||
|
cwd: root,
|
||||||
|
ignore: ignoreRules,
|
||||||
|
});
|
||||||
|
const tauriConfPath = paths[0];
|
||||||
|
return tauriConfPath ? resolve(root, tauriConfPath, '..') : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getWorkspaceDir(dir: string): string | null {
|
||||||
|
const rootPath = dir;
|
||||||
|
while (dir.length && dir[dir.length - 1] !== sep) {
|
||||||
|
const manifestPath = join(dir, 'Cargo.toml');
|
||||||
|
if (existsSync(manifestPath)) {
|
||||||
|
const toml = parseToml(readFileSync(manifestPath).toString());
|
||||||
|
// @ts-expect-error
|
||||||
|
if (toml.workspace?.members) {
|
||||||
|
// @ts-expect-error
|
||||||
|
const members: string[] = toml.workspace.members;
|
||||||
|
if (members.some((m) => resolve(dir, m) === rootPath)) {
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dir = normalize(join(dir, '..'));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTargetDir(crateDir: string): string {
|
||||||
|
const def = join(crateDir, 'target');
|
||||||
|
if ('CARGO_TARGET_DIR' in process.env) {
|
||||||
|
return process.env.CARGO_TARGET_DIR ?? def;
|
||||||
|
}
|
||||||
|
let dir = crateDir;
|
||||||
|
while (dir.length && dir[dir.length - 1] !== sep) {
|
||||||
|
let cargoConfigPath = join(dir, '.cargo/config');
|
||||||
|
if (!existsSync(cargoConfigPath)) {
|
||||||
|
cargoConfigPath = join(dir, '.cargo/config.toml');
|
||||||
|
}
|
||||||
|
if (existsSync(cargoConfigPath)) {
|
||||||
|
const cargoConfig = parseToml(readFileSync(cargoConfigPath).toString());
|
||||||
|
// @ts-ignore
|
||||||
|
if (cargoConfig.build?.['target-dir']) {
|
||||||
|
// @ts-ignore
|
||||||
|
return cargoConfig.build['target-dir'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dir = normalize(join(dir, '..'));
|
||||||
|
}
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hasDependency(dependencyName: string, root: string): boolean {
|
||||||
|
const packageJson = getPackageJson(root);
|
||||||
|
return (
|
||||||
|
packageJson &&
|
||||||
|
(packageJson.dependencies?.[dependencyName] ||
|
||||||
|
packageJson.devDependencies?.[dependencyName])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function usesYarn(root: string): boolean {
|
||||||
|
return existsSync(join(root, 'yarn.lock'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function usesPnpm(root: string): boolean {
|
||||||
|
return existsSync(join(root, 'pnpm-lock.yaml'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function execCommand(
|
||||||
|
command: string,
|
||||||
|
args: string[],
|
||||||
|
{ cwd }: { cwd?: string } = {}
|
||||||
|
): Promise<void> {
|
||||||
|
console.log(`running ${command}`, args);
|
||||||
|
|
||||||
|
return execa(command, args, {
|
||||||
|
cwd,
|
||||||
|
stdio: 'inherit',
|
||||||
|
env: { FORCE_COLOR: '0' },
|
||||||
|
}).then();
|
||||||
|
}
|
||||||
|
|
||||||
|
function _getJson5Config(contents: string): TauriConfig | null {
|
||||||
|
try {
|
||||||
|
const config = JSON5.parse(contents) as TauriConfig;
|
||||||
|
return config;
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getConfig(path: string): TauriConfig {
|
||||||
|
const contents = readFileSync(path).toString();
|
||||||
|
try {
|
||||||
|
const config = JSON.parse(contents) as TauriConfig;
|
||||||
|
return config;
|
||||||
|
} catch (e) {
|
||||||
|
let json5Conf = _getJson5Config(contents);
|
||||||
|
if (json5Conf === null) {
|
||||||
|
json5Conf = _getJson5Config(
|
||||||
|
readFileSync(join(path, '..', 'tauri.conf.json5')).toString()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (json5Conf) {
|
||||||
|
return json5Conf;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getInfo(
|
||||||
|
root: string,
|
||||||
|
inConfigPath: string | null = null
|
||||||
|
): Info {
|
||||||
|
const tauriDir = getTauriDir(root);
|
||||||
|
if (tauriDir !== null) {
|
||||||
|
const configPath = inConfigPath ?? join(tauriDir, 'tauri.conf.json');
|
||||||
|
let name;
|
||||||
|
let version;
|
||||||
|
let wixLanguage: string | string[] | { [language: string]: unknown } =
|
||||||
|
'en-US';
|
||||||
|
const config = getConfig(configPath);
|
||||||
|
if (config.package) {
|
||||||
|
name = config.package.productName;
|
||||||
|
version = config.package.version;
|
||||||
|
if (config.package.version?.endsWith('.json')) {
|
||||||
|
const packageJsonPath = join(tauriDir, config.package.version);
|
||||||
|
const contents = readFileSync(packageJsonPath).toString();
|
||||||
|
version = JSON.parse(contents).version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!(name && version)) {
|
||||||
|
const manifestPath = join(tauriDir, 'Cargo.toml');
|
||||||
|
const cargoManifest = parseToml(
|
||||||
|
readFileSync(manifestPath).toString()
|
||||||
|
) as unknown as CargoManifest;
|
||||||
|
name = name || cargoManifest.package.name;
|
||||||
|
version = version || cargoManifest.package.version;
|
||||||
|
}
|
||||||
|
if (config.tauri?.bundle?.windows?.wix?.language) {
|
||||||
|
wixLanguage = config.tauri.bundle.windows.wix.language;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(name && version)) {
|
||||||
|
console.error('Could not determine package name and version');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
tauriPath: tauriDir,
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
wixLanguage,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
const packageJson = getPackageJson(root);
|
||||||
|
const appName = packageJson
|
||||||
|
? (packageJson.displayName || packageJson.name).replace(/ /g, '-')
|
||||||
|
: 'app';
|
||||||
|
const version = packageJson ? packageJson.version : '0.1.0';
|
||||||
|
return {
|
||||||
|
tauriPath: null,
|
||||||
|
name: appName,
|
||||||
|
version,
|
||||||
|
wixLanguage: 'en-US',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,13 +2,12 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"target": "es6",
|
"target": "es2015",
|
||||||
"allowJs": true,
|
|
||||||
"pretty": true,
|
"pretty": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"importHelpers": true
|
"importHelpers": true
|
||||||
},
|
},
|
||||||
"baseUrl": "."
|
"include": ["./src"]
|
||||||
}
|
}
|
||||||
|
|||||||