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",
|
||||
"prepublish": [
|
||||
{
|
||||
"command": "yarn",
|
||||
"command": "pnpm install",
|
||||
"dryRunCommand": true
|
||||
},
|
||||
{
|
||||
@@ -29,18 +29,8 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"path": "./packages/action",
|
||||
"path": "./",
|
||||
"manager": "javascript",
|
||||
"publish": [
|
||||
"git tag v${ pkgFile.versionMajor } -f",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
"@tauri-apps/action-core": patch
|
||||
"action": patch
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
"@tauri-apps/action-core": patch
|
||||
'action': patch
|
||||
---
|
||||
|
||||
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`.
|
||||
|
||||
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
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: covector status
|
||||
|
||||
@@ -9,13 +9,17 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 12
|
||||
node-version: 16
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
- name: install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 7.x.x
|
||||
- name: git config
|
||||
run: |
|
||||
git config --global user.name "${{ github.event.pusher.name }}"
|
||||
|
||||
8
.github/workflows/test-action.yml
vendored
@@ -15,18 +15,22 @@ jobs:
|
||||
- name: setup node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 14
|
||||
node-version: 16
|
||||
- name: install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
- name: install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 7.x.x
|
||||
- name: install dependencies (ubuntu only)
|
||||
if: matrix.platform == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev librsvg2-dev patchelf
|
||||
- name: install example dependencies
|
||||
run: yarn
|
||||
run: pnpm install
|
||||
working-directory: ./packages/action/__fixtures__/example
|
||||
- uses: ./
|
||||
env:
|
||||
|
||||
7
.gitignore
vendored
@@ -44,10 +44,3 @@ target
|
||||
|
||||
# lockfiles, as a lib we don't need to 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'
|
||||
runs:
|
||||
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,
|
||||
"workspaces": [
|
||||
"packages/core",
|
||||
"packages/cli",
|
||||
"packages/action"
|
||||
"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",
|
||||
"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": {
|
||||
"covector": "0.7.3",
|
||||
"prettier": "^2.8.0"
|
||||
"@types/node": "16.18.11",
|
||||
"@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 { getOctokit, context } from '@actions/github';
|
||||
import { GitHub } from '@actions/github/lib/utils';
|
||||
import fs from 'fs';
|
||||
|
||||
interface Release {
|
||||
id: number;
|
||||
@@ -25,7 +26,7 @@ function allReleases(
|
||||
);
|
||||
}
|
||||
|
||||
export default async function createRelease(
|
||||
export async function createRelease(
|
||||
tagName: string,
|
||||
releaseName: string,
|
||||
body?: string,
|
||||
@@ -44,11 +45,12 @@ export default async function createRelease(
|
||||
const { owner, repo } = context.repo;
|
||||
|
||||
const bodyPath = core.getInput('body_path', { required: false });
|
||||
let bodyFileContent = null;
|
||||
let bodyFileContent: string | null = null;
|
||||
if (bodyPath !== '' && !!bodyPath) {
|
||||
try {
|
||||
bodyFileContent = fs.readFileSync(bodyPath, { encoding: 'utf8' });
|
||||
} catch (error) {
|
||||
//@ts-ignore
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
}
|
||||
@@ -60,7 +62,7 @@ export default async function createRelease(
|
||||
if (draft) {
|
||||
console.log(`Looking for a draft release with tag ${tagName}...`);
|
||||
for await (const response of allReleases(github)) {
|
||||
let releaseWithTag = response.data.find(
|
||||
const releaseWithTag = response.data.find(
|
||||
(release) => release.tag_name === tagName
|
||||
);
|
||||
if (releaseWithTag) {
|
||||
@@ -84,6 +86,7 @@ export default async function createRelease(
|
||||
console.log(`Found release with tag ${tagName}.`);
|
||||
}
|
||||
} catch (error) {
|
||||
// @ts-ignore
|
||||
if (error.status === 404 || error.message === 'release not found') {
|
||||
console.log(`Couldn't find release with tag ${tagName}. Creating one.`);
|
||||
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 uploadReleaseAssets from './upload-release-assets';
|
||||
import uploadVersionJSON from './upload-version-json';
|
||||
import createRelease from './create-release';
|
||||
import {
|
||||
getPackageJson,
|
||||
buildProject,
|
||||
getInfo,
|
||||
execCommand,
|
||||
} from '@tauri-apps/action-core';
|
||||
import type { BuildOptions } from '@tauri-apps/action-core';
|
||||
import { platform } from 'os';
|
||||
import { join, resolve, dirname, basename } from 'path';
|
||||
|
||||
import * as core from '@actions/core';
|
||||
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> {
|
||||
try {
|
||||
const projectPath = resolve(
|
||||
@@ -137,6 +136,7 @@ async function run(): Promise<void> {
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
// @ts-ignore
|
||||
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 { getAssetName } from './utils';
|
||||
|
||||
export default async function uploadAssets(
|
||||
releaseId: number,
|
||||
assets: Artifact[]
|
||||
) {
|
||||
import { getOctokit, context } from '@actions/github';
|
||||
|
||||
import { getAssetName } from './utils';
|
||||
import type { Artifact } from './types';
|
||||
|
||||
export async function uploadAssets(releaseId: number, assets: Artifact[]) {
|
||||
if (process.env.GITHUB_TOKEN === undefined) {
|
||||
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 uploadAssets from './upload-release-assets';
|
||||
import fetch from 'node-fetch';
|
||||
import { arch, platform } from 'os';
|
||||
import { getAssetName } from './utils';
|
||||
import { Artifact } from '@tauri-apps/action-core';
|
||||
import { platform } from 'os';
|
||||
import { resolve } from 'path';
|
||||
|
||||
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,
|
||||
notes,
|
||||
tagName,
|
||||
@@ -28,7 +44,7 @@ export default async function uploadVersionJSON({
|
||||
|
||||
const versionFilename = 'latest.json';
|
||||
const versionFile = resolve(process.cwd(), versionFilename);
|
||||
const versionContent = {
|
||||
const versionContent: VersionContent = {
|
||||
version,
|
||||
notes,
|
||||
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(
|
||||
Buffer.from(assetData).toString()
|
||||
@@ -81,7 +97,7 @@ export default async function uploadVersionJSON({
|
||||
|
||||
// Untagged release downloads won't work after the release was published
|
||||
downloadUrl = downloadUrl?.replace(
|
||||
/\/download\/(untagged-[^\/]+)\//,
|
||||
/\/download\/(untagged-[^/]+)\//,
|
||||
tagName ? `/download/${tagName}/` : '/latest/download/'
|
||||
);
|
||||
|
||||
@@ -104,7 +120,7 @@ export default async function uploadVersionJSON({
|
||||
: arch;
|
||||
|
||||
// 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(),
|
||||
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": {
|
||||
"strict": true,
|
||||
"module": "esnext",
|
||||
"target": "es6",
|
||||
"allowJs": true,
|
||||
"target": "es2015",
|
||||
"pretty": true,
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true
|
||||
},
|
||||
"baseUrl": "."
|
||||
"include": ["./src"]
|
||||
}
|
||||
|
||||