🚧 wip(actions): some github actions wip

This commit is contained in:
Pauline 2024-08-04 05:31:41 +02:00
parent 6aca816ec6
commit 58f6e999ba
No known key found for this signature in database
GPG key ID: 722BB181973296AE
33 changed files with 2854 additions and 518 deletions

View file

@ -3,5 +3,3 @@ rustflags = [
"-C",
"link-args=/STACK:16777220"
]
[env]

5
.gitattributes vendored Normal file
View file

@ -0,0 +1,5 @@
* text=auto eol=lf
Cargo.lock -diff linguist-generated
pnpm-lock.yaml -diff linguist-generated
.github/actions/publish-artifacts/dist/index.js -diff linguist-generated=true
.github/actions/clippy/dist/index.js -diff linguist-generated=true

46
.github/actions/clippy/action.yml vendored Normal file
View file

@ -0,0 +1,46 @@
name: Run Clippy
description: Run Clippy
inputs:
github_token:
description: GitHub token
required: false
default: ${{ github.token }}
clippy_flags:
description: clippy flags
required: false
default: ''
tool_name:
description: tool name to use for reviewdog reporter
required: false
default: Clippy
level:
description: 'report level for reviewdog [info,warning,error]'
required: false
default: error
reporter:
description: 'reporter of reviewdog command [github-pr-check,github-pr-review,github-check].'
required: false
default: github-pr-check
filter_mode:
description: filtering for the reviewdog command [added,diff_context,file,nofilter].
required: false
default: added
fail_on_error:
description: exit code for reviewdog when errors are found [true,false]
required: false
default: 'false'
reviewdog_flags:
description: additional reviewdog flags
required: false
default: ''
workdir:
description: working directory relative to the root directory
required: false
default: .
reviewdog_version:
description: the version of reviewdog
required: false
default: latest
runs:
using: node20
main: dist/index.js

3
.github/actions/clippy/dist/index.js generated vendored Normal file

File diff suppressed because one or more lines are too long

28
.github/actions/clippy/package.json vendored Normal file
View file

@ -0,0 +1,28 @@
{
"name": "@onelauncher/action-clippy",
"version": "1.0.0-alpha.1",
"private": true,
"description": "Next-generation open source Minecraft launcher",
"license": "GPL-3.0-only",
"repository": {
"type": "git",
"url": "git@github.com:polyfrost/onelauncher",
"directory": ".github/actions/clippy"
},
"bugs": "https://github.com/polyfrost/onelauncher/issues",
"sideEffects": false,
"scripts": {
"build": "ncc build src/index.ts --minify"
},
"dependencies": {
"@actions/core": "^1.10.1",
"@actions/exec": "^1.1.1",
"@actions/http-client": "^2.2.1",
"@actions/io": "^1.1.3",
"@actions/tool-cache": "^2.0.1",
"pathe": "^1.1.2"
},
"devDependencies": {
"@vercel/ncc": "^0.38.1"
}
}

153
.github/actions/clippy/src/index.ts vendored Normal file
View file

@ -0,0 +1,153 @@
import os from 'node:os';
import { promises as fs } from 'node:fs';
import process from 'node:process';
import { Buffer } from 'node:buffer';
import { join, relative } from 'pathe';
import { rmRF } from '@actions/io';
import { exec } from '@actions/exec';
import core from '@actions/core';
import { installReviewdog } from './installer';
async function run(): Promise<void> {
const runnerTmpdir = process.env.RUNNER_TEMP || os.tmpdir();
const tmpdir = await fs.mkdtemp(join(runnerTmpdir, 'reviewdog-'));
try {
const reviewdogVersion = core.getInput('reviewdog_version') || 'latest';
const toolName = core.getInput('tool_name') || 'clippy';
const clippyFlags = core.getInput('clippy_flags');
const clippyDebug = core.getInput('clippy_debug') || 'false';
const level = core.getInput('level') || 'error';
const reporter = core.getInput('reporter') || 'github-pr-check';
const filterMode = core.getInput('filter_mode') || 'added';
const failOnError = core.getInput('fail_on_error') || 'false';
const reviewdogFlags = core.getInput('reviewdog_flags');
const workdir = core.getInput('workdir') || '.';
const cwd = relative(process.env.GITHUB_WORKSPACE || process.cwd(), workdir);
const reviewdog = await core.group('installing reviewdog', async () => await installReviewdog(reviewdogVersion, tmpdir));
const code = await core.group(
'running clippy',
async (): Promise<number> => {
const output: string[] = [];
await exec(
'cargo',
[
'clippy',
'--color',
'never',
'-q',
'--message-format',
'json',
...parse(clippyFlags),
],
{
cwd,
ignoreReturnCode: true,
silent: clippyDebug !== 'true',
listeners: {
stdline: (line: string) => {
const content: CompilerMessage = JSON.parse(line);
if (content.reason !== 'compiler-message') {
core.debug('ignore all but `compiler-message`');
return;
}
if (content.message.code === null) {
core.debug('message code is missing, ignore it');
return;
}
const span = content.message.spans[0]!;
const messageLevel = content.message.level === 'warning' ? 'w' : 'e';
const rendered = reporter === 'github-pr-review'
? ` \n<pre><code>${content.message.rendered}</code></pre>\n__END__`
: `${content.message.rendered}\n__END__`;
const ret = `${span.file_name}:${span.line_start}:${span.column_start}:${messageLevel}:${rendered}`;
output.push(ret);
},
},
},
);
process.env.REVIEWDOG_GITHUB_API_TOKEN = core.getInput('github_token');
return await exec(
reviewdog,
[
'-efm=<pre><code>%E%f:%l:%c:%t:%m',
'-efm=%E%f:%l:%c:%t:%m',
'-efm=%Z__END__',
'-efm=%C%m</code></pre>',
'-efm=%C%m',
'-efm=%C',
`-name=${toolName}`,
`-reporter=${reporter}`,
`-filter-mode=${filterMode}`,
`-fail-on-error=${failOnError}`,
`-level=${level}`,
...parse(reviewdogFlags),
],
{
cwd,
input: Buffer.from(output.join('\n'), 'utf-8'),
ignoreReturnCode: true,
},
);
},
);
if (code !== 0)
core.setFailed(`reviewdog exited with status code: ${code}`);
}
catch (error) {
if (error instanceof Error)
core.setFailed(error.message);
}
finally {
try {
await rmRF(tmpdir);
}
catch (error) {
if (error instanceof Error)
core.info(`cleanup failed: ${error.message}`);
else
core.info(`cleanup failed: ${error}`);
}
}
}
function parse(flags: string): string[] {
flags = flags.trim();
if (flags === '')
return [];
return flags.split(/\s+/);
}
interface CompilerMessage {
reason: string;
message: {
code: Code;
level: string;
message: string;
rendered: string;
spans: Span[];
};
}
interface Code {
code: string;
explanation?: string;
}
interface Span {
file_name: string;
is_primary: boolean;
line_start: number;
line_end: number;
column_start: number;
column_end: number;
}
run();

44
.github/actions/clippy/src/installer.ts vendored Normal file
View file

@ -0,0 +1,44 @@
import process from 'node:process';
import { join } from 'pathe';
import { error } from '@actions/core';
import { Headers, HttpClient, HttpCodes } from '@actions/http-client';
import { downloadTool, extractTar } from '@actions/tool-cache';
const getUrl = (version: string, platform: string, arch: string) => `https://github.com/reviewdog/reviewdog/releases/download/v${version}/reviewdog_${version}_${platform}_${arch}.tar.gz`;
interface Release {
tag_name: string;
}
export async function installReviewdog(tag: string, directory: string): Promise<string> {
const version = await tagToVersion(tag, 'reviewdog', 'reviewdog');
const platform = process.platform === 'darwin' ? 'Darwin' : process.platform === 'linux' ? 'Linux' : process.platform === 'win32' ? 'Windows' : '';
const arch = process.arch === 'x64' ? 'x86_64' : process.arch === 'arm64' ? process.arch : '';
if (platform === '')
throw new Error(`unsupported platform ${process.platform}!`);
if (arch === '')
throw new Error(`unsupported architecture: ${process.arch}!`);
const url = getUrl(version, platform, arch);
const archivePath = await downloadTool(url);
const extractedDir = await extractTar(archivePath, directory);
const executablePath = `reviewdog${process.platform === 'win32' ? '.exe' : ''}`;
return join(extractedDir, executablePath);
}
async function tagToVersion(tag: string, owner: string, repo: string): Promise<string> {
const url = `https://github.com/${owner}/${repo}/releases/${tag}`;
const client = new HttpClient('clippy/v1');
const headers = { [Headers.Accept]: 'application/json' };
const response = await client.getJson<Release>(url, headers);
if (response.statusCode !== HttpCodes.OK)
error(`${url} returned unexpected HTTP status code: ${response.statusCode}`);
if (!response.result)
throw new Error(`unable to find '${tag}' - use 'latest' or see https://github.com/${owner}/${repo}/releases for details`);
return response.result.tag_name.replace(/^v/, '');
}

9
.github/actions/clippy/tsconfig.json vendored Normal file
View file

@ -0,0 +1,9 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"allowImportingTsExtensions": false,
"noEmit": true,
"skipLibCheck": true
},
"exclude": ["**/dist/**"]
}

View file

@ -0,0 +1,14 @@
name: Publish Artifacts
description: Publish Artifacts
inputs:
target:
description: Target triples for build artifact
profile:
description: '''debug'' or ''release'''
os:
description: '''darwin'', ''windows'', or ''linux'''
arch:
description: '''x86_64'' or ''aarch64'''
runs:
using: node20
main: dist/index.js

79
.github/actions/publish-artifacts/dist/index.js generated vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,26 @@
{
"name": "@onelauncher/action-publish-artifacts",
"version": "1.0.0-alpha.1",
"private": true,
"description": "Next-generation open source Minecraft launcher",
"license": "GPL-3.0-only",
"repository": {
"type": "git",
"url": "git@github.com:polyfrost/onelauncher",
"directory": ".github/actions/publish-artifacts"
},
"bugs": "https://github.com/polyfrost/onelauncher/issues",
"sideEffects": false,
"scripts": {
"build": "ncc build src/index.ts --minify"
},
"dependencies": {
"@actions/artifact": "^2.1.9",
"@actions/core": "^1.10.1",
"@actions/glob": "^0.4.0",
"@actions/io": "^1.1.3"
},
"devDependencies": {
"@vercel/ncc": "^0.38.1"
}
}

View file

@ -0,0 +1,119 @@
import client from '@actions/artifact';
import core from '@actions/core';
import glob from '@actions/glob';
import io from '@actions/io';
import { exists } from '@actions/io/lib/io-util';
type OS = 'darwin' | 'windows' | 'linux';
type Arch = 'x64' | 'arm64';
type Profile = 'debug' | 'release' | 'dev' | 'dev-debug';
interface Updater {
bundle: string;
bundleExt: string;
archiveExt: string;
}
interface TargetConfig {
bundle: string;
ext: string;
}
interface BuildTarget {
updater: false | Updater;
standalone: Array<TargetConfig>;
}
const osTargets = {
darwin: {
updater: {
bundle: 'macos',
bundleExt: 'app',
archiveExt: 'tar.gz',
},
standalone: [
{ ext: 'dmg', bundle: 'dmg' },
],
},
windows: {
updater: {
bundle: 'msi',
bundleExt: 'msi',
archiveExt: 'zip',
},
standalone: [
{ ext: 'msi', bundle: 'msi' },
],
},
linux: {
updater: false, // TODO
standalone: [
{ ext: 'deb', bundle: 'deb' },
],
},
} satisfies Record<OS, BuildTarget>;
const getInput = <T = string>(name: string): T => core.getInput(name) as T;
const os: OS = getInput('os');
const arch: Arch = getInput('arch');
const profile: Profile = getInput('profile');
const target = getInput('target');
const bundleDir = `target/${target}/${profile}/bundle`;
const artifactsDir = '.artifacts';
const artifactBase = `OneLauncher-${os}-${arch}`;
const frontendBundle = 'apps/frontend/dist.tar.xz';
const updaterName = `OneLauncher-Updater-${os}-${arch}`;
const frontendName = `OneLauncher-Frontend-${os}-${arch}`;
const globFiles = async (pattern: string): Promise<string[]> => await (await glob.create(pattern)).glob();
async function uploadFrontend() {
if (!(await exists(frontendBundle))) {
console.error('frontend archive missing!');
return;
}
await client.uploadArtifact(frontendName, [frontendBundle], 'apps/frontend');
}
async function uploadUpdater(updater: BuildTarget['updater']) {
if (!updater)
return;
const { bundle, bundleExt, archiveExt } = updater;
const fullExt = `${bundleExt}.${archiveExt}`;
const files = await globFiles(`${bundleDir}/${bundle}/*.${fullExt}*`);
const updaterPath = files.find(f => f.endsWith(fullExt));
if (!updaterPath)
throw new Error(`failed to find updater path in ${files}`);
const artifactPath = `${artifactsDir}/${updaterName}.${archiveExt}`;
await io.cp(updaterPath, artifactPath);
await io.cp(`${updaterPath}.sig`, `${artifactPath}.sig`);
await client.uploadArtifact(updaterName, [artifactPath, `${artifactPath}.sig`], artifactsDir);
}
async function uploadStandalone({ bundle, ext }: TargetConfig) {
const files = await globFiles(`${bundleDir}/${bundle}/*.${ext}*`);
const standalonePath = files.find(f => f.endsWith(ext));
if (!standalonePath)
throw new Error(`failed to find standalone path in ${files}`);
const artifactName = `${artifactBase}.${ext}`;
const artifactPath = `${artifactsDir}/${artifactName}`;
await io.cp(standalonePath, artifactPath, { recursive: true });
await client.uploadArtifact(artifactName, [artifactPath], artifactsDir);
}
async function run() {
await io.mkdirP(artifactsDir);
const { updater, standalone } = osTargets[os];
await Promise.all([
uploadUpdater(updater),
uploadFrontend(),
...standalone.map(uploadStandalone),
]);
}
run();

View file

@ -0,0 +1,9 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"allowImportingTsExtensions": false,
"noEmit": true,
"skipLibCheck": true
},
"exclude": ["**/dist/**"]
}

26
.github/actions/setup-pnpm/action.yml vendored Normal file
View file

@ -0,0 +1,26 @@
name: Setup Pnpm
description: Setup Pnpm
inputs:
token:
description: GitHub token
required: false
default: ''
runs:
using: composite
steps:
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Install Node.js
uses: actions/setup-node@v4
with:
token: ${{ input.token }}
check-latest: true
node-version-file: .nvmrc
- name: Install dependencies
shell: ${{ runner.os == 'Windows' && 'powershell' || 'bash' }}
env:
NODE_ENV: debug
GITHUB_TOKEN: ${{ inputs.token }}
run: pnpm install --frozen-lockfile

34
.github/actions/setup-rust/action.yml vendored Normal file
View file

@ -0,0 +1,34 @@
name: Setup Rust
description: Setup Rust
inputs:
target:
description: Toolchain target triple
required: false
save-cache:
description: Whether or not to save the rust cache
required: false
default: 'false'
restore-cache:
description: Whether or not to restore the rust cache
required: false
default: 'true'
runs:
using: composite
steps:
- name: Install Rust
uses: IronCoreLabs/rust-toolchain@v1
with:
target: ${{ inputs.target }}
components: clippy, rustfmt
- name: Cache Rust
if: ${{ inputs.restore-cache == 'true' }}
uses: Swatinem/rust-cache@v2
with:
key: ${{ inputs.target }}
save-if: ${{ inputs.save-cache }}
shared-key: stable-cache
- name: Prepare Cargo
shell: bash
run: echo '{}' | pnpm dlx -y mustache - .cargo/config.toml.mustache .cargo/config.toml

68
.github/actions/setup-system/action.yml vendored Normal file
View file

@ -0,0 +1,68 @@
name: Setup System and Rust
description: Setup System and Rust
inputs:
token:
description: GitHub token
required: false
default: ''
target:
description: Toolchain target triple
required: false
setup-arg:
description: Argument for the system setup script
required: false
default: ''
save-cache:
description: Whether or not to save the system cache
required: false
default: 'false'
runs:
using: composite
steps:
- name: (macOS) - Install bash@latest
shell: bash
if: ${{ runner.os == 'macOS' }}
run: brew install bash
- name: (linux) - Install mold@latest
shell: bash
if: ${{ runner.os == 'Linux' }}
run: |
curl -L# 'https://github.com/rui314/mold/releases/download/v2.32.1/mold-2.32.1-x86_64-linux.tar.gz' \
| sudo tar -xzf- -C /usr/local
- name: (linux) - Cleanup Runner
shell: bash
if: ${{ runner.os == 'Linux' }}
run: |
set -eux
if dpkg -l | grep i386; then
sudo apt-get purge --allow-remove-essential libc6-i386 ".*:i386" || true
sudo dpkg --remove-architecture i386 || true
fi
sudo apt-get remove libunwind-* || true
- name: Setup Rust and Dependencies
uses: ./.github/actions/setup-rust
with:
target: ${{ inputs.target }}
save-cache: ${{ inputs.save-cache }}
- name: (linux/macOS) - Setup System
shell: bash
if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }}
run: ./packages/scripts/setup.sh ${{ inputs.setup-arg }}
- name: (windows) - Setup System
shell: powershell
run: ./packages/scripts/setup.ps1
- name: Setup Shared Libraries
shell: bash
env:
TARGET_TRIPLE: ${{ inputs.triple }}
GITHUB_TOKEN: ${{ inputs.token }}
run: |
pnpm install
env NODE_ENV=debug pnpm prepare

View file

@ -0,0 +1,171 @@
name: Build
on: [pull_request, merge_group]
env:
ONELAUNCHER_CUSTOM_APT_FLAGS: --no-install-recommends
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
RUST_BACKTRACE: short
RUSTUP_MAX_RETRIES: 10
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
es:
name: EcmaScript Checks
runs-on: ubuntu-22.04
timeout-minutes: 7
permissions: {}
steps:
- name: Prepare Target
run: echo "PR_FETCH_DEPTH=$(( ${{ github.event.pull_request.commits }} + 1))" >> "${GITHUB_ENV}"
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
fetch-depth: ${{ env.PR_FETCH_DEPTH }}
- name: Setup Pnpm
uses: ./.github/actions/setup-pnpm
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Linting
run: pnpm lint:es
# - name: Testing
# run: pnpm test:es
rust:
name: Rust Checks
runs-on: ubuntu-22.04
timeout-minutes: 10
permissions:
contents: read
steps:
- name: Maximize build space
if: ${{ runner.os == 'Linux' }}
uses: easimon/maximize-build-space@fc881a613ad2a34aca9c9624518214ebc21dfc0c
with:
swap-size-mb: 4096
root-reserve-mb: 6144
remove-dotnet: 'true'
remove-codeql: 'true'
remove-haskell: 'true'
remove-docker-images: 'true'
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- name: (windows) - Setup Target
if: ${{ runner.os == 'Windows' }}
shell: powershell
run: |
New-Item -ItemType Directory -Force -Path C:\onelauncher_target
New-Item -Path target -ItemType Junction -Value C:\onelauncher_target
- name: Prepare Target
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36
continue-on-error: true
id: filter
with:
filters: |
changes:
- ${{ runner.os == 'Windows' && 'packages/scripts/setup.ps1' || 'packages/scripts/setup.sh' }}
- 'packages/scripts/prepare.ts'
- 'apps/cli/*/**'
- 'apps/desktop/*/**'
- 'apps/testing/*/**'
- 'packages/core/**'
- 'packages/macros/**'
- 'Cargo.toml'
- 'Cargo.lock'
- '.github/workflows/build.yml'
- name: Setup System
if: steps.filter.outcome != 'success' || steps.filter.outputs.changes == 'true'
uses: ./.github/actions/setup-system
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Run Rustfmt
if: steps.filter.outcome != 'success' || steps.filter.outputs.changes == 'true'
run: cargo fmt --all -- --check
clippy:
strategy:
fail-fast: true
matrix:
settings:
- host: macos-13
target: x86_64-apple-darwin
- host: macos-14
target: aarch64-apple-darwin
- host: windows-latest
target: x86_64-pc-windows-msvc
- host: ubuntu-22.04
target: x86_64-unknown-linux-gnu
runs-on: ${{ matrix.settings.host }}
name: Clippy (${{ matrix.settings.host }})
timeout-minutes: 45
permissions:
contents: read
steps:
- name: Maximize build space
if: ${{ runner.os == 'Linux' }}
uses: easimon/maximize-build-space@fc881a613ad2a34aca9c9624518214ebc21dfc0c
with:
swap-size-mb: 4096
root-reserve-mb: 6144
remove-dotnet: 'true'
remove-codeql: 'true'
remove-haskell: 'true'
remove-docker-images: 'true'
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- name: (windows) - Setup Target
if: ${{ runner.os == 'Windows' }}
shell: powershell
run: |
New-Item -ItemType Directory -Force -Path C:\onelauncher_target
New-Item -Path target -ItemType Junction -Value C:\onelauncher_target
- name: Prepare Target
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36
continue-on-error: true
id: filter
with:
filters: |
changes:
- ${{ runner.os == 'Windows' && 'packages/scripts/setup.ps1' || 'packages/scripts/setup.sh' }}
- 'packages/scripts/prepare.ts'
- 'apps/cli/*/**'
- 'apps/desktop/*/**'
- 'apps/testing/*/**'
- 'packages/core/**'
- 'packages/macros/**'
- 'Cargo.toml'
- 'Cargo.lock'
- '.github/workflows/build.yml'
- name: Setup System
if: steps.filter.outcome != 'success' || steps.filter.outputs.changes == 'true'
uses: ./.github/actions/setup-system
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Run Clippy
if: steps.filter.outcome != 'success' || steps.filter.outputs.changes == 'true'
uses: ./.github/actions/clippy
with:
reporter: github-pr-review
tool_name: 'Clippy (${{ matrix.settings.host }})'
filter_mode: diff_context
github_token: ${{ secrets.GITHUB_TOKEN }}
clippy_flags: --workspace --all-features --locked
fail_on_error: true

86
.github/workflows/cache.yml vendored Normal file
View file

@ -0,0 +1,86 @@
name: Cache
on:
push:
branches:
- main
schedule:
- cron: '0 0 * * *'
pull_request:
paths:
- .github/workflows/cache.yml
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
RUST_BACKTRACE: short
RUSTUP_MAX_RETRIES: 10
jobs:
cache:
strategy:
fail-fast: true
matrix:
settings:
- host: macos-13
target: x86_64-apple-darwin
- host: macos-14
target: aarch64-apple-darwin
- host: windows-latest
target: x86_64-pc-windows-msvc
- host: ubuntu-22.04
target: x86_64-unknown-linux-gnu
name: Make Cache
runs-on: ${{ matrix.settings.host }}
if: github.repository == 'polyfrost/onelauncher'
permissions: {}
timeout-minutes: 150
steps:
- name: Maximize build space
if: ${{ runner.os == 'Linux' }}
uses: easimon/maximize-build-space@fc881a613ad2a34aca9c9624518214ebc21dfc0c
with:
swap-size-mb: 4096
root-reserve-mb: 6144
remove-dotnet: 'true'
remove-codeql: 'true'
remove-haskell: 'true'
remove-docker-images: 'true'
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- name: (windows) - Setup Target
if: ${{ runner.os == 'Windows' }}
shell: powershell
run: |
New-Item -ItemType Directory -Force -Path C:\onelauncher_target
New-Item -Path target -ItemType Junction -Value C:\onelauncher_target
- name: Setup System
uses: ./.github/actions/setup-system
with:
token: ${{ secrets.GITHUB_TOKEN }}
target: ${{ matrix.settings.target }}
save-cache: 'true'
- name: (debug) - Test
run: cargo test --workspace --all-features --no-run --locked --target ${{ matrix.settings.target }}
- name: (release) - Test
run: cargo test --workspace --all-features --no-run --locked --release --target ${{ matrix.settings.target }}
- name: (debug) - Build
run: cargo build --quiet --workspace --all-features --target ${{ matrix.settings.target }}
- name: (release) - Build
run: cargo build --quiet --workspace --all-features --release --target ${{ matrix.settings.target }}
- name: (debug) - Clippy
run: cargo clippy --workspace --all-features --target ${{ matrix.settings.target }}

View file

@ -0,0 +1,132 @@
name: Release
on:
pull_request:
paths:
- .github/workflows/release.yml
workflow_dispatch:
env:
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
RUSTUP_MAX_RETRIES: 10
jobs:
desktop:
strategy:
matrix:
settings:
- host: macos-13
target: x86_64-apple-darwin
bundles: app,dmg
os: darwin
arch: x86_64
- host: macos-14
target: aarch64-apple-darwin
bundles: app,dmg
os: darwin
arch: aarch64
- host: windows-latest
target: x86_64-pc-windows-msvc
bundles: msi
os: windows
arch: x86_64
- host: ubuntu-22.04
target: x86_64-unknown-linux-gnu
bundles: deb
os: linux
arch: x86_64
name: Desktop (${{ matrix.settings.target }})
runs-on: ${{ matrix.settings.host }}
steps:
- name: Maximize build space
if: ${{ runner.os == 'Linux' }}
uses: easimon/maximize-build-space@fc881a613ad2a34aca9c9624518214ebc21dfc0c
with:
swap-size-mb: 4096
root-reserve-mb: 6144
remove-dotnet: 'true'
remove-codeql: 'true'
remove-haskell: 'true'
remove-docker-images: 'true'
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- name: (windows) - Setup Target
if: ${{ runner.os == 'Windows' }}
shell: powershell
run: |
New-Item -ItemType Directory -Force -Path C:\onelauncher_target
New-Item -Path target -ItemType Junction -Value C:\onelauncher_target
# - name: (macOS) - Download Apple key
# i f: ${ { runner.os == 'macOS' }}
# run: |
# mkdir -p ~/.appstoreconnect/private_keys/
# cd ~/.appstoreconnect/private_keys/
# echo ${ { secrets.APPLE_API_KEY_B64 }} >> AuthKey_${ { secrets.APPLE_API_KEY }}.p8.base64
# base64 --decode -i AuthKey_$ {{ secrets.APPLE_API_KEY }}.p8.base64 -o AuthKey_${ { secrets.APPLE_API_KEY }}.p8
# rm AuthKey_${ { secrets.APPLE_API_KEY }}.p8.base64
# - name: (macOS) - Install Apple key
# i f: ${ { runner.os == 'macOS' }}
# uses: apple-actions/import-codesign-certs@v2
# with:
# p12-file-base64: ${ { secrets.APPLE_CERTIFICATE }}
# p12-password: ${ { secrets.APPLE_CERTIFICATE_PASSWORD }}
- name: Setup System
uses: ./.github/actions/setup-system
# env:
# APPLE_SIGNING_IDENTITY: ${ { secrets.APPLE_SIGNING_IDENTITY }}
with:
token: ${{ secrets.GITHUB_TOKEN }}
target: ${{ matrix.settings.target }}
- name: Setup Pnpm
uses: ./.github/actions/setup-pnpm
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Build
run: pnpm desktop build --ci -v --target ${{ matrix.settings.target }} --bundles ${{ matrix.settings.bundles }},updater
# env:
# TAURI_SIGNING_PRIVATE_KEY: $ {{ secrets.TAURI_PRIVATE_KEY }}
# TAURI_SIGNING_PRIVATE_KEY_PASSWORD: $ {{ secrets.TAURI_KEY_PASSWORD }}
# ENABLE_CODE_SIGNING: $ {{ secrets.APPLE_CERTIFICATE }}
# APPLE_CERTIFICATE: $ {{ secrets.APPLE_CERTIFICATE }}
# APPLE_CERTIFICATE_PASSWORD: $ {{ secrets.APPLE_CERTIFICATE_PASSWORD }}
# APPLE_SIGNING_IDENTITY: $ {{ secrets.APPLE_SIGNING_IDENTITY }}
# APPLE_PROVIDER_SHORT_NAME: $ {{ secrets.APPLE_PROVIDER_SHORT_NAME }}
# APPLE_API_ISSUER: $ {{ secrets.APPLE_API_ISSUER }}
# APPLE_API_KEY: $ {{ secrets.APPLE_API_KEY }}
# SENTRY_AUTH_TOKEN: $ {{ secrets.SENTRY_AUTH_TOKEN }}
- name: (linux) - Build Frontend
if: ${{ runner.os == 'Linux' }}
run: |
set -eux
XZ_OPT='-T0 -7' tar -cJf apps/frontend/dist.tar.xz -C apps/frontend/dist .
- name: Publish Artifacts
uses: ./.github/actions/publish-artifacts
with:
os: ${{ matrix.settings.os }}
arch: ${{ matrix.settings.arch }}
target: ${{ matrix.settings.target }}
profile: release
release:
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
name: Create Release
needs: desktop
permissions:
contents: write
steps:
- name: Download Artifacts
uses: actions/download-artifact@v4
# - name: Create Relesae
# u

View file

@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Stale
uses: actions/stale@v9
uses: actions/stale@3f3b0175e8c66fb49b9a6d5a0cd1f8436d4c3ab6
with:
close-issue-message: >
This issue was closed because it has been stale for 10 days with no activity.

1
.nvmrc Normal file
View file

@ -0,0 +1 @@
20

View file

@ -1,15 +1,15 @@
[workspace]
resolver = "2"
resolver = "2" # virtual workspace resolver so we don't need a root package
members = [
"apps/testing",
"apps/desktop",
"packages/core",
"packages/macros"
"apps/testing", # onelauncher_test -- test the core crate in a cli setting
"apps/desktop", # onelauncher_gui -- the rust code for our tauri app
"packages/core", # onelauncher -- the rust core for onelauncher
"packages/macros" # onelauncher_macros -- utility procedural macros for onelauncher
]
[workspace.package]
[workspace.package] # sets default [package] settings for workspace members
license = "GPL-3.0-only"
edition = "2021"
edition = "2021" # latest rust edition
repository = "https://github.com/Polyfrost/OneLauncher"
documentation = "https://docs.polyfrost.org/onelauncher"
readme = "README.md"
@ -18,9 +18,10 @@ authors = [
"Polyfrost",
"Polyfrost Contributors"
]
version = "1.0.0-alpha.1"
version = "1.0.0-alpha.1" # bump this manually for now
[workspace.dependencies]
# # ============= WORKSPACE ============= # #
# best practice to define all workspace crates in the root
# even if they are not use, with no features enabled.
onelauncher = { path = "./packages/core" }
@ -28,7 +29,8 @@ onelauncher_macros = { path = "./packages/macros" }
onelauncher_gui = { path = "./apps/desktop" }
onelauncher_test = { path = "./apps/testing" }
# tauri uses latest crates.io beta channel
# # ============= TAURI ============= # #
# tauri uses latest crates.io rc channel
# (temporarily can use v2 and main branches if necessary)
tauri = { version = "=2.0.0-rc.0", features = [
"rustls-tls",
@ -38,8 +40,8 @@ tauri = { version = "=2.0.0-rc.0", features = [
"protocol-asset"
] }
# tauri-build is the codegen utility for our tauri buildscript.
tauri-build = { version = "=2.0.0-rc.0" }
# tauri-plugin-shell adds a bridge for opening urls and paths in the frontend.
tauri-plugin-shell = { version = "=2.0.0-rc.0" }
# tauri-plugin-window-state saves the window position and size to be restored.
@ -53,6 +55,7 @@ tauri-plugin-updater = { version = "=2.0.0-rc.0" }
# tauri-plugin-dialog adds a bridge for opening file manager and message dialogs.
tauri-plugin-dialog = { version = "=2.0.0-rc.0" }
# # ============= CORE ============= # #
# rspc is used as a faster and more intuitive replacement for tauri-specta
# commands/apis that don't depend on tauri. rather than using the tauri
# event and invoke apis for handling api calling, it creates a router which
@ -83,7 +86,7 @@ specta = { version = "=2.0.0-rc.19", features = [
"time"
] }
# tauri-specta
# tauri-specta is the tauri adapter for specta.
tauri-specta = { version = "=2.0.0-rc.14", features = [
"javascript",
"typescript",
@ -96,10 +99,13 @@ specta-typescript = { version = "=0.0.6" }
# rspc-specta2 is the specta v2 (rc) adapter for rspc.
rspc-tauri2 = { version = "=0.0.1" }
# all other dependencies are updated to latest crates.io release channel
# # ============= MINECRAFT ============= # #
# core utilities for minecraft and mod management with pulseflow apis
interpulse = { version = "1", features = [ "specta" ] }
# # ============= SECURITY ============= # #
thiserror = { version = "1.0" }
anyhow = { version = "1.0" }
tracing = { version = "0.1" }
tracing-subscriber = { version = "0.3", features = [
"chrono",
@ -115,28 +121,28 @@ sentry = { version = "0.34", default-features = false, features = [
"anyhow",
"debug-images"
] }
iota_stronghold = { version = "2.1" }
zeroize = { version = "1.8", features = [ "zeroize_derive" ] }
notify = { version = "6.1", default-features = false }
notify-debouncer-mini = { version = "0.4", default-features = false }
uuid = { version = "1.8", features = [
"serde",
"v4"
] }
tokio = { version = "1.38", features = [ "full" ] }
async-tungstenite = { version = "0.26", features = [
"tokio-runtime",
"tokio-rustls-native-certs"
] }
strum = { version = "0.23", features = [ "derive" ] }
once_cell = { version = "1.19" }
tokio-stream = { version = "0.1.15", features = [ "fs" ] }
# # ============= SERIALIZATION ============= # #
serde = { version = "1.0", features = [ "derive" ] }
serde_json = { version = "1.0" }
serde_ini = { version = "0.2" }
regex = { version = "1.10" }
url = { version = "2.5.2" }
strum = { version = "0.23", features = [ "derive" ] }
chrono = { version = "0.4", features = [ "serde" ] }
rand = { version = "0.8.5" }
byteorder = { version = "1.5.0" }
base64 = { version = "0.22" }
p256 = { version = "0.13.2", features = [ "ecdsa" ] }
uuid = { version = "1.8", features = [
"serde",
"v4"
] }
# # ============= NETWORK ============= # #
reqwest = { version = "0.12", default-features = false, features = [
"json",
"stream",
@ -147,43 +153,49 @@ reqwest = { version = "0.12", default-features = false, features = [
"gzip",
"brotli"
] }
iota_stronghold = { version = "2.1" }
zeroize = { version = "1.8", features = [ "zeroize_derive" ] }
quote = { version = "1.0" }
syn = { version = "2.0", features = [ "full" ] }
async-tungstenite = { version = "0.26", features = [
"tokio-runtime",
"tokio-rustls-native-certs"
] }
webbrowser = { version = "1.0" }
# # ============= SYSTEM ============= # #
tokio = { version = "1.38", features = [ "full" ] }
tokio-stream = { version = "0.1.15", features = [ "fs" ] }
notify = { version = "6.1", default-features = false }
notify-debouncer-mini = { version = "0.4", default-features = false }
tempfile = { version = "3.10" }
dunce = { version = "1.0.4" }
serde_json = { version = "1.0" }
serde_ini = { version = "0.2" }
zip = { version = "0.6" }
thiserror = { version = "1.0" }
anyhow = { version = "1.0" }
dirs = { version = "5.0" }
discord-rich-presence = { version = "0.2" }
winreg = { version = "0.52" }
paste = { version = "1.0" }
dashmap = { version = "6.0", features = [ "serde" ] }
sha1_smol = { version = "1.0", features = [ "std" ] }
sha2 = { version = "0.10" }
bytes = { version = "1.6" }
lazy_static = { version = "1.4" }
indicatif = { version = "0.17" }
futures = { version = "0.3" }
async-recursion = { version = "1.1" }
async_zip = { version = "0.0.17", features = [ "full" ] }
async-compression = { version = "0.4.12", features = [
"flate2",
"tokio"
] }
flate2 = { version = "1.0" }
regex = { version = "1.10" }
sha1_smol = { version = "1.0", features = [ "std" ] }
sha2 = { version = "0.10" }
bytes = { version = "1.6" }
# # ============= UTILITY ============= # #
once_cell = { version = "1.19" }
quote = { version = "1.0" }
syn = { version = "2.0", features = [ "full" ] }
discord-rich-presence = { version = "0.2" }
winreg = { version = "0.52" }
paste = { version = "1.0" }
dashmap = { version = "6.0", features = [ "serde" ] }
lazy_static = { version = "1.4" }
indicatif = { version = "0.17" }
futures = { version = "0.3" }
async-recursion = { version = "1.1" }
sysinfo = { version = "0.31", features = [ "serde" ] }
sys-info = { version = "0.9" }
whoami = { version = "1.5" }
cocoa = { version = "0.25" }
objc = { version = "0.2" }
webbrowser = { version = "1.0" }
url = { version = "2.5.2" }
[workspace.dependencies.prisma-client-rust]
git = "https://github.com/brendonovich/prisma-client-rust"
@ -215,47 +227,47 @@ default-features = false
[profile.dev]
# add debug symbols/logic and optimize for reduced build time (parallel)
debug = true
opt-level = 0
strip = "none"
incremental = true
split-debuginfo = "unpacked"
lto = false
codegen-units = 256
rpath = false
panic = "unwind"
debug = true # add debug info
opt-level = 0 # reduce optimizations
strip = "none" # don't remove debug symbols
incremental = true # enable incremental compilation
split-debuginfo = "unpacked" # unpack debug info
lto = false # disable link time optimizations, reduce compile time
codegen-units = 256 # make parallel incremental builds faster
rpath = false # disable rpath
panic = "unwind" # add unwind panic logic because some deps require it
# add debug symbols/logic and optimize for reduced build time (parallel)
[profile.dev-debug]
inherits = "dev"
split-debuginfo = "none"
opt-level = 0
debug = "full"
strip = "none"
lto = "off"
codegen-units = 256
incremental = true
inherits = "dev" # extend the dev profile
split-debuginfo = "none" # don't split debug info
opt-level = 0 # reduce optimizations
debug = "full" # add full debug info
strip = "none" # don't remove debug symbols
lto = "off" # disable link time optimizations, reduce compile time
codegen-units = 256 # make parallel incremental builds faster
incremental = true # enable incremental compilation
# set the settings for build scripts and proc-macros.
[profile.dev.build-override]
opt-level = 3
opt-level = 3 # optimize build
# set the default for dependencies, except workspace members.
[profile.dev.package."*"]
opt-level = 3
incremental = false
opt-level = 3 # optimize build
incremental = false # disable incremental compilation
# set the default for dependencies, except workspace members.
[profile.dev-debug.package."*"]
inherits = "dev"
opt-level = 3
debug = "full"
incremental = false
inherits = "dev" # extend the dev profile
opt-level = 3 # optimize build
debug = "full" # add full debug info
incremental = false # disable incremental compilation
# optimize for speed and reduce size for release
[profile.release]
panic = "abort" # strip panic cleanup logic
codegen-units = 1 # compile crate one after another for better optimization
lto = true
lto = true # enable link time optimization
opt-level = "s" # optimize binary
strip = true # remove debug symbols

View file

@ -59,11 +59,9 @@ pub async fn check_for_update(app: tauri::AppHandle) -> Result<Option<Update>, S
app.emit(
"updater",
update
.clone()
.map_or(UpdateEvent::NoUpdateAvailable, |u| {
UpdateEvent::UpdateAvailable { update: u }
}),
update.clone().map_or(UpdateEvent::NoUpdateAvailable, |u| {
UpdateEvent::UpdateAvailable { update: u }
}),
)
.ok();

View file

@ -1,5 +1,3 @@
// define the `changelogithub` configuration so we can automatically generate
// changelogs with github actions upon each `pnpm release`.
export default {
types: {
chore: { title: '🔨 Chores' },
@ -14,5 +12,4 @@ export default {
deploy: { title: '🚀 Deployments' },
wip: { title: '🚧 Experiments' },
},
capitalize: false,
};

View file

@ -1,7 +1,6 @@
// @ts-check
import petal from '@flowr/eslint-config';
import { defineConfig } from '@flowr/eslint-config';
export default petal({
export default defineConfig({
typescript: true,
solid: true,
unocss: false,

View file

@ -28,14 +28,12 @@
"test": "pnpm test:vi && pnpm --filter=./* run test",
"format": "pnpm format:es && pnpm format:rs",
"lint": "pnpm lint:es && pnpm lint:rs",
"frontend": "pnpm --filter @onelauncher/frontend -- ",
"client": "pnpm --filter @onelauncher/client -- ",
"desktop": "pnpm --filter @onelauncher/desktop -- ",
"core": "cd packages/core && cargo",
"testing": "cd apps/testing && cargo",
"tauri": "cd apps/desktop && cargo",
"test:vi": "pnpm vitest run",
"test:update": "pnpm vitest -u",
"test:ui": "pnpm vitest --ui",
@ -52,12 +50,14 @@
]
},
"devDependencies": {
"@flowr/eslint-config": "^3.10.2",
"@flowr/eslint-config": "^3.10.4",
"@types/node": "^22.1.0",
"@vitest/ui": "^2.0.5",
"bumpp": "^9.4.2",
"eslint": "^9.8.0",
"changelogen": "^0.5.5",
"eslint": "npm:eslint-ts-patch@9.8.0-1",
"eslint-plugin-solid": "^0.14.1",
"eslint-ts-patch": "9.8.0-1",
"ts-node": "^10.9.2",
"tsx": "~4.16.5",
"typescript": "^5.5.4",

View file

@ -104,7 +104,7 @@ pub async fn run_default(path: &ClusterPath) -> crate::Result<Arc<RwLock<Process
#[onelauncher_macros::memory]
pub async fn run(
path: &ClusterPath,
creds: Option<&MinecraftCredentials>
creds: Option<&MinecraftCredentials>,
) -> crate::Result<Arc<RwLock<ProcessorChild>>> {
if let Some(creds) = creds {
run_credentials(path, creds).await

View file

@ -118,7 +118,8 @@ pub async fn wait_for(process: &mut ProcessorChild) -> crate::Result<()> {
pub async fn get_pid_by_uuid(uuid: Uuid) -> crate::Result<u32> {
let state = State::get().await?;
let processor = state.processor.read().await;
Ok(processor.get(uuid)
Ok(processor
.get(uuid)
.ok_or(anyhow::anyhow!("process not found"))?
.read()
.await

View file

@ -18,7 +18,7 @@
"tauri": "pnpm tsx tauri.ts"
},
"dependencies": {
"@flowr/utils": "^3.10.2",
"@flowr/utils": "^3.10.4",
"execa": "^9.3.0",
"pathe": "^1.1.2",
"semver": "^7.6.3",

View file

@ -93,7 +93,8 @@ case "$(uname)" in
# Tauri dependencies
set -- build-essential curl wget file libssl-dev libgtk-3-dev librsvg2-dev \
libwebkit2gtk-4.1-dev libayatana-appindicator3-dev libxdo-dev libdbus-1-dev libvips42
libwebkit2gtk-4.1-dev libayatana-appindicator3-dev libxdo-dev libdbus-1-dev libvips42 \
llvm-dev libclang-dev clang nasm perl
sudo apt-get -y update
sudo apt-get -y install "$@"
@ -102,7 +103,7 @@ case "$(uname)" in
echo "Installing dependencies with pacman..."
# Tauri dependencies
set -- appmenu-gtk-module libappindicator-gtk3 base-devel curl wget file openssl gtk3 librsvg webkit2gtk-4.1 libayatana-appindicator dbus xdotool libvips
set -- appmenu-gtk-module libappindicator-gtk3 base-devel curl wget file openssl gtk3 librsvg webkit2gtk-4.1 libayatana-appindicator dbus xdotool libvips clang nasm perl
sudo pacman -Sy --needed "$@"
elif has dnf; then
@ -116,7 +117,7 @@ case "$(uname)" in
fi
# Tauri dependencies
set -- openssl webkit2gtk4.1-devel openssl-devel curl wget file libappindicator-gtk3-devel librsvg2-devel libxdo-devel dbus vips
set -- openssl webkit2gtk4.1-devel openssl-devel curl wget file libappindicator-gtk3-devel librsvg2-devel libxdo-devel dbus vips clang clang-devel nasm perl-core
sudo dnf install "$@"
elif has apk; then
@ -126,7 +127,8 @@ case "$(uname)" in
# Tauri dependencies
set -- build-base curl wget file openssl-dev gtk+3.0-dev librsvg-dev \
webkit2gtk-4.1-dev libayatana-indicator-dev xdotool-dev dbus-dev vips
webkit2gtk-4.1-dev libayatana-indicator-dev xdotool-dev dbus-dev vips \
llvm16-dev clang16 nasm perl
sudo apk add "$@"
elif has emerge; then

2110
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,4 @@
packages:
- apps/*
- packages/*
- .github/actions/*

View file

@ -26,6 +26,7 @@
"noEmit": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"verbatimModuleSyntax": true,
"skipLibCheck": true