feat: integrate StarLight updates and improve font settings and skin editor loading
Some checks failed
Axolotl desktop CI / guardrails (push) Has been cancelled
Axolotl desktop CI / desktop (macos-latest) (push) Has been cancelled
Axolotl desktop CI / desktop (ubuntu-latest) (push) Has been cancelled
Axolotl desktop CI / desktop (windows-latest) (push) Has been cancelled
Axolotl desktop CI / website (push) Has been cancelled
Repository checks / typos (push) Has been cancelled
Repository checks / tombi (push) Has been cancelled
Rust checks / shear (push) Has been cancelled
Sync source to CNB / Sync Git ref (push) Has been cancelled
Some checks failed
Axolotl desktop CI / guardrails (push) Has been cancelled
Axolotl desktop CI / desktop (macos-latest) (push) Has been cancelled
Axolotl desktop CI / desktop (ubuntu-latest) (push) Has been cancelled
Axolotl desktop CI / desktop (windows-latest) (push) Has been cancelled
Axolotl desktop CI / website (push) Has been cancelled
Repository checks / typos (push) Has been cancelled
Repository checks / tombi (push) Has been cancelled
Rust checks / shear (push) Has been cancelled
Sync source to CNB / Sync Git ref (push) Has been cancelled
This commit is contained in:
@ -62,11 +62,42 @@ for (const target of targets) {
|
||||
}
|
||||
}
|
||||
|
||||
function digest(asset) {
|
||||
if (typeof asset.digest !== 'string' || !asset.digest.startsWith('sha256:')) {
|
||||
throw new Error(`Release asset ${asset.name} has no SHA-256 digest`)
|
||||
}
|
||||
return asset.digest.slice('sha256:'.length)
|
||||
}
|
||||
|
||||
const apt = {}
|
||||
for (const target of [
|
||||
{ platform: 'linux-x86_64', assetSuffix: '_amd64.deb' },
|
||||
{ platform: 'linux-aarch64', assetSuffix: '_arm64.deb' },
|
||||
]) {
|
||||
const matches = assets.filter((asset) => asset.name?.endsWith(target.assetSuffix))
|
||||
if (matches.length !== 1) {
|
||||
throw new Error(
|
||||
`Expected one release asset ending in ${target.assetSuffix}, found ${matches.length}`,
|
||||
)
|
||||
}
|
||||
const asset = matches[0]
|
||||
const url = asset.browser_download_url ?? asset.url
|
||||
if (!url || !Number.isSafeInteger(asset.size) || asset.size <= 0) {
|
||||
throw new Error(`Release asset ${asset.name} has invalid download metadata`)
|
||||
}
|
||||
apt[target.platform] = {
|
||||
url,
|
||||
sha256: digest(asset),
|
||||
size: asset.size,
|
||||
}
|
||||
}
|
||||
|
||||
const manifest = {
|
||||
version: tag.replace(/^v/, ''),
|
||||
notes: release.body ?? '',
|
||||
pub_date: new Date().toISOString(),
|
||||
platforms,
|
||||
apt,
|
||||
}
|
||||
|
||||
fs.writeFileSync(outputPath, `${JSON.stringify(manifest, null, 2)}\n`)
|
||||
|
||||
70
scripts/axolotl/create-update-manifest.test.mjs
Normal file
70
scripts/axolotl/create-update-manifest.test.mjs
Normal file
@ -0,0 +1,70 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import crypto from 'node:crypto'
|
||||
import fs from 'node:fs'
|
||||
import os from 'node:os'
|
||||
import path from 'node:path'
|
||||
import { spawnSync } from 'node:child_process'
|
||||
|
||||
const root = path.resolve(import.meta.dirname, '..', '..')
|
||||
const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'starlight-update-manifest-'))
|
||||
const releasePath = path.join(directory, 'release.json')
|
||||
const signaturesPath = path.join(directory, 'signatures')
|
||||
const outputPath = path.join(directory, 'latest.json')
|
||||
const tag = 'v1.9.7'
|
||||
const updaterAssets = [
|
||||
'Axolotl_Launcher_universal.app.tar.gz',
|
||||
'Axolotl_Launcher_1.9.7_aarch64.AppImage.tar.gz',
|
||||
'Axolotl_Launcher_1.9.7_amd64.AppImage.tar.gz',
|
||||
'Axolotl_Launcher_1.9.7_x64-setup.nsis.zip',
|
||||
]
|
||||
const debAssets = [
|
||||
'Axolotl_Launcher_1.9.7_amd64.deb',
|
||||
'Axolotl_Launcher_1.9.7_arm64.deb',
|
||||
]
|
||||
|
||||
try {
|
||||
fs.mkdirSync(signaturesPath)
|
||||
for (const name of updaterAssets) {
|
||||
fs.writeFileSync(path.join(signaturesPath, `${name}.sig`), 'signature'.repeat(8))
|
||||
}
|
||||
fs.writeFileSync(
|
||||
releasePath,
|
||||
JSON.stringify({
|
||||
body: '测试版本',
|
||||
assets: [...updaterAssets, ...debAssets].map((name, index) => ({
|
||||
name,
|
||||
size: index + 1024,
|
||||
digest: `sha256:${crypto.createHash('sha256').update(name).digest('hex')}`,
|
||||
browser_download_url: `https://github.com/Mystic-Stars/Axolotl/releases/download/${tag}/${name}`,
|
||||
})),
|
||||
}),
|
||||
)
|
||||
|
||||
const create = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'scripts/axolotl/create-update-manifest.mjs',
|
||||
releasePath,
|
||||
signaturesPath,
|
||||
tag,
|
||||
outputPath,
|
||||
],
|
||||
{ cwd: root, encoding: 'utf8' },
|
||||
)
|
||||
assert.equal(create.status, 0, create.stderr)
|
||||
|
||||
const manifest = JSON.parse(fs.readFileSync(outputPath, 'utf8'))
|
||||
assert.equal(manifest.version, '1.9.7')
|
||||
assert.deepEqual(Object.keys(manifest.apt).sort(), ['linux-aarch64', 'linux-x86_64'])
|
||||
assert.equal(manifest.apt['linux-x86_64'].size, 1028)
|
||||
assert.match(manifest.apt['linux-aarch64'].sha256, /^[0-9a-f]{64}$/)
|
||||
|
||||
const verify = spawnSync(
|
||||
process.execPath,
|
||||
['scripts/axolotl/verify-update-manifest.mjs', outputPath, tag],
|
||||
{ cwd: root, encoding: 'utf8' },
|
||||
)
|
||||
assert.equal(verify.status, 0, verify.stderr)
|
||||
} finally {
|
||||
fs.rmSync(directory, { recursive: true, force: true })
|
||||
}
|
||||
49
scripts/axolotl/skin-editor-bridge.test.mjs
Normal file
49
scripts/axolotl/skin-editor-bridge.test.mjs
Normal file
@ -0,0 +1,49 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import test from 'node:test'
|
||||
import { runInNewContext } from 'node:vm'
|
||||
|
||||
const source = readFileSync(
|
||||
new URL('../../apps/app/src/skin_editor_bridge.js', import.meta.url),
|
||||
'utf8',
|
||||
)
|
||||
|
||||
function createFrame(url = 'http://axolotl-skin.localhost/index.html?embed=skin') {
|
||||
const listeners = new Map()
|
||||
const messages = []
|
||||
const window = {
|
||||
parent: { postMessage: (message) => messages.push(message) },
|
||||
addEventListener: (type, handler) => listeners.set(type, handler),
|
||||
}
|
||||
runInNewContext(source, { window, location: new URL(url), URLSearchParams })
|
||||
return { window, listeners, messages }
|
||||
}
|
||||
|
||||
test('reports startup exceptions to the launcher', () => {
|
||||
const frame = createFrame()
|
||||
frame.listeners.get('error')({ message: 'ReferenceError: missing editor dependency' })
|
||||
assert.equal(frame.messages[0].type, 'axolotl-skin-load-error')
|
||||
assert.match(frame.messages[0].error, /missing editor dependency/)
|
||||
})
|
||||
|
||||
test('reports rejected module imports even when the editor handles the rejection', async () => {
|
||||
const frame = createFrame()
|
||||
frame.window.blockbenchBundleReady = Promise.reject(new Error('Failed to fetch editor module'))
|
||||
frame.listeners.get('DOMContentLoaded')()
|
||||
await Promise.resolve()
|
||||
assert.equal(frame.messages[0].error, 'Failed to fetch editor module')
|
||||
})
|
||||
|
||||
test('does not install the bridge on unrelated pages', () => {
|
||||
for (const url of ['https://skin.starlight.cool/', 'http://axolotl-skin.localhost/index.html']) {
|
||||
assert.equal(createFrame(url).listeners.size, 0)
|
||||
}
|
||||
})
|
||||
|
||||
test('ignores resize observer notifications', () => {
|
||||
const frame = createFrame()
|
||||
frame.listeners.get('error')({
|
||||
message: 'ResizeObserver loop completed with undelivered notifications.',
|
||||
})
|
||||
assert.equal(frame.messages.length, 0)
|
||||
})
|
||||
@ -42,4 +42,22 @@ for (const platform of requiredPlatforms) {
|
||||
}
|
||||
}
|
||||
|
||||
for (const platform of ['linux-aarch64', 'linux-x86_64']) {
|
||||
const artifact = manifest.apt?.[platform]
|
||||
if (
|
||||
!artifact ||
|
||||
typeof artifact.sha256 !== 'string' ||
|
||||
!/^[0-9a-f]{64}$/i.test(artifact.sha256) ||
|
||||
!Number.isSafeInteger(artifact.size) ||
|
||||
artifact.size <= 0
|
||||
) {
|
||||
throw new Error(`Missing Debian update for ${platform}`)
|
||||
}
|
||||
|
||||
const url = new URL(artifact.url)
|
||||
if (url.protocol !== 'https:') {
|
||||
throw new Error(`Unexpected Debian update URL for ${platform}: ${artifact.url}`)
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Verified signed ${source} updater manifest for ${expectedVersion}`)
|
||||
|
||||
Reference in New Issue
Block a user