feat: update from own releases
This commit is contained in:
1 parent
be8a500937
commit
9676c94430
7 files changed
+330
-4
No files matched your search
@@ -16,6 +16,10 @@ on:
|
||||
description: Upstream tag to build instead of the one in upstream.txt
|
||||
type: string
|
||||
required: false
|
||||
revision:
|
||||
description: Which release of the upstream version this is, for the updater
|
||||
type: string
|
||||
required: false
|
||||
outputs:
|
||||
version:
|
||||
description: Version the app was built as
|
||||
@@ -27,6 +31,7 @@ concurrency:
|
||||
|
||||
env:
|
||||
UPSTREAM_REF: ${{ inputs.upstream-ref }}
|
||||
MODRINTH_ENHANCED_REVISION: ${{ inputs.revision }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -104,12 +109,19 @@ jobs:
|
||||
shell: bash
|
||||
run: scripts/check.sh
|
||||
|
||||
# Without the key, as for a pull request from a fork, the build simply
|
||||
# has no updater.
|
||||
- name: Build
|
||||
shell: bash
|
||||
env:
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
||||
run: scripts/build.sh
|
||||
|
||||
- name: Check the build output
|
||||
shell: bash
|
||||
env:
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
run: scripts/check.sh
|
||||
|
||||
- name: Upload installers
|
||||
|
||||
@@ -33,6 +33,7 @@ jobs:
|
||||
outputs:
|
||||
upstream: ${{ steps.check.outputs.upstream }}
|
||||
tag: ${{ steps.check.outputs.tag }}
|
||||
revision: ${{ steps.check.outputs.revision }}
|
||||
proceed: ${{ steps.check.outputs.proceed }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -64,20 +65,22 @@ jobs:
|
||||
)"
|
||||
|
||||
if [ -z "$last" ]; then
|
||||
revision=1
|
||||
tag="$upstream"
|
||||
else
|
||||
revision="${last%% *}"
|
||||
last_tag="${last#* }"
|
||||
git fetch --no-tags --depth=1 origin "refs/tags/$last_tag:refs/tags/$last_tag"
|
||||
# Only what goes into the build counts, not docs or CI.
|
||||
if git diff --quiet "$last_tag" HEAD -- patches scripts; then
|
||||
if git diff --quiet "$last_tag" HEAD -- patches scripts updater.pub; then
|
||||
echo "$last_tag already ships the current patches; nothing to do."
|
||||
echo "proceed=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
tag="$upstream-$((revision + 1))"
|
||||
revision="$(( ${last%% *} + 1 ))"
|
||||
tag="$upstream-$revision"
|
||||
fi
|
||||
|
||||
echo "revision=$revision" >> "$GITHUB_OUTPUT"
|
||||
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
||||
echo "proceed=true" >> "$GITHUB_OUTPUT"
|
||||
echo "Releasing $tag"
|
||||
@@ -89,6 +92,8 @@ jobs:
|
||||
uses: ./.github/workflows/build.yml
|
||||
with:
|
||||
upstream-ref: ${{ needs.detect.outputs.upstream }}
|
||||
revision: ${{ needs.detect.outputs.revision }}
|
||||
secrets: inherit
|
||||
|
||||
release:
|
||||
name: Release
|
||||
@@ -118,6 +123,63 @@ jobs:
|
||||
path: artifacts
|
||||
merge-multiple: true
|
||||
|
||||
# The app looks for updates in releases/latest/download/latest.json.
|
||||
# Spaces in asset names become dots first, as GitHub would make them, so
|
||||
# the addresses written into it are exact. A release without signatures
|
||||
# stops here: every install it reached could never update again.
|
||||
- name: Write the update manifest
|
||||
env:
|
||||
TAG: ${{ needs.detect.outputs.tag }}
|
||||
UPSTREAM: ${{ needs.detect.outputs.upstream }}
|
||||
REVISION: ${{ needs.detect.outputs.revision }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
for file in artifacts/*' '*; do
|
||||
if [ -e "$file" ]; then mv "$file" "${file// /.}"; fi
|
||||
done
|
||||
python3 - <<'EOF'
|
||||
import datetime, json, os, pathlib
|
||||
|
||||
artifacts = pathlib.Path("artifacts")
|
||||
tag = os.environ["TAG"]
|
||||
repository = os.environ["GITHUB_REPOSITORY"]
|
||||
|
||||
# The app's version is the upstream one. A revision comes along as
|
||||
# build metadata, which the app compares itself.
|
||||
version = os.environ["UPSTREAM"].removeprefix("v")
|
||||
if int(os.environ["REVISION"]) > 1:
|
||||
version += "+" + os.environ["REVISION"]
|
||||
|
||||
|
||||
def signed(suffix):
|
||||
matches = [p for p in artifacts.iterdir() if p.name.endswith(suffix)]
|
||||
if len(matches) != 1:
|
||||
raise SystemExit(f"Expected one *{suffix}, found {[p.name for p in matches]}")
|
||||
signature = pathlib.Path(f"{matches[0]}.sig")
|
||||
if not signature.is_file():
|
||||
raise SystemExit(f"{matches[0].name} is not signed: is TAURI_SIGNING_PRIVATE_KEY set?")
|
||||
return {
|
||||
"signature": signature.read_text().strip(),
|
||||
"url": f"https://github.com/{repository}/releases/download/{tag}/{matches[0].name}",
|
||||
}
|
||||
|
||||
|
||||
macos = signed(".app.tar.gz")
|
||||
manifest = {
|
||||
"version": version,
|
||||
"notes": f"Modrinth Enhanced {tag}",
|
||||
"pub_date": datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||
"platforms": {
|
||||
"linux-x86_64": signed(".AppImage"),
|
||||
"windows-x86_64": signed("-setup.exe"),
|
||||
"darwin-x86_64": macos,
|
||||
"darwin-aarch64": macos,
|
||||
},
|
||||
}
|
||||
(artifacts / "latest.json").write_text(json.dumps(manifest, indent=2) + "\n")
|
||||
print((artifacts / "latest.json").read_text())
|
||||
EOF
|
||||
|
||||
- name: Publish the release
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
|
||||
@@ -30,6 +30,7 @@ works.
|
||||
| `0015-Use-the-desktop-s-file-picker-...` | File pickers on Linux are the desktop's own, such as KDE's, through the XDG desktop portal. |
|
||||
| `0016-Show-the-account-in-the-title-bar-...` | With the right sidebar folded away, the Minecraft account is shown in the title bar and managed from there. |
|
||||
| `0017-Start-on-Wayland-with-an-NVIDIA-GPU` | The app no longer crashes at start under Wayland with the NVIDIA driver. |
|
||||
| `0018-Update-from-Modrinth-Enhanced-s-...` | Updates come from this project's own signed releases rather than Modrinth's. |
|
||||
|
||||
### Offline accounts
|
||||
|
||||
@@ -155,6 +156,14 @@ without making anyone more private.
|
||||
neither ends up in a build; removing the entries would mean carrying a patch against the lockfile
|
||||
for no practical gain.
|
||||
|
||||
### Updates
|
||||
|
||||
The app updates itself from this project's releases on GitHub: on Windows, on macOS, and as an
|
||||
AppImage on Linux. Updates are signed with this project's own key, whose public half is
|
||||
`updater.pub`, and Modrinth is no longer asked, since its update would be the official app.
|
||||
Installs from the AUR, a `.deb` or a `.rpm` are updated like any other package; the app shows a
|
||||
notice with a button to the release when there is a new one.
|
||||
|
||||
## Relationship to the official app
|
||||
|
||||
Modrinth Enhanced keeps the upstream bundle identifier, which means it uses **the same data
|
||||
@@ -218,6 +227,10 @@ scripts/prepare.sh
|
||||
release of that upstream version, it is released again as `v0.21.2-2`, `v0.21.2-3` and so on.
|
||||
The app and installers still carry the upstream version: RPM and the Windows installers do not
|
||||
accept a suffix in it.
|
||||
- **Updates** are published with every release as `latest.json`, next to installers signed with the
|
||||
`TAURI_SIGNING_PRIVATE_KEY` secret. A release without signatures fails instead of shipping, since
|
||||
every install it reached could never update again. Builds without the secret, such as pull
|
||||
requests from forks, have no updater.
|
||||
|
||||
`scripts/check.sh` is what makes the automation trustworthy. A patch can apply cleanly and still
|
||||
stop doing its job if upstream moves the thing it was holding down, so the checks assert the
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Modrinth Enhanced <patches@modrinth-enhanced.invalid>
|
||||
Date: Tue, 15 Sep 2026 18:43:17 +0200
|
||||
Subject: [PATCH] Update from Modrinth Enhanced's own releases
|
||||
|
||||
The updater asked Modrinth, whose update is the official app and would
|
||||
replace this one. It now takes this project's own signed releases, with
|
||||
the endpoint and key given at build time by scripts/build.sh.
|
||||
|
||||
Revisions of one upstream version share the app's version, since the
|
||||
installers refuse a suffix in it, so a release carries its revision as
|
||||
build metadata and the comparison looks at that. On Linux only the
|
||||
AppImage updates itself; other installs, and builds without the updater,
|
||||
get a notice with a button to the release on GitHub.
|
||||
---
|
||||
apps/app-frontend/src/App.vue | 63 ++++++++++++++++++++++++-----------
|
||||
apps/app/src/main.rs | 32 ++++++++++++++++++
|
||||
apps/app/tauri.conf.json | 2 +-
|
||||
3 files changed, 76 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/apps/app-frontend/src/App.vue b/apps/app-frontend/src/App.vue
|
||||
index 5cbe7d8..dfdcdb1 100644
|
||||
--- a/apps/app-frontend/src/App.vue
|
||||
+++ b/apps/app-frontend/src/App.vue
|
||||
@@ -1888,9 +1888,13 @@ const updatePopupMessages = defineMessages({
|
||||
defaultMessage: `Modrinth App v{version} has finished downloading. Reload to update now, or automatically when you close Modrinth App.`,
|
||||
},
|
||||
linuxBody: {
|
||||
- id: 'app.update-popup.body.linux',
|
||||
+ id: 'app.update-popup.body.linux-release',
|
||||
defaultMessage:
|
||||
- 'Modrinth App v{version} is available. Use your package manager to update for the latest features and fixes!',
|
||||
+ 'Modrinth Enhanced v{version} is available. Update it with your package manager, or download it from the release on GitHub.',
|
||||
+ },
|
||||
+ openRelease: {
|
||||
+ id: 'app.update-popup.open-release',
|
||||
+ defaultMessage: 'Open release',
|
||||
},
|
||||
reload: {
|
||||
id: 'app.update-popup.reload',
|
||||
@@ -2065,28 +2069,47 @@ async function checkUpdates() {
|
||||
)
|
||||
}
|
||||
|
||||
+// A .deb or .rpm install, or a build without the updater, is only told about
|
||||
+// a new release: this project's own on GitHub, not Modrinth's, whose update
|
||||
+// would be the official app.
|
||||
async function checkLinuxUpdates() {
|
||||
try {
|
||||
- const [response, currentVersion] = await Promise.all([
|
||||
- fetch('https://launcher-files.modrinth.com/updates.json'),
|
||||
+ const [repository, currentVersion, currentRevision] = await Promise.all([
|
||||
+ invoke('release_repository'),
|
||||
getVersion(),
|
||||
+ invoke('app_revision'),
|
||||
])
|
||||
- const updates = await response.json()
|
||||
- const latestVersion = updates?.version
|
||||
-
|
||||
- if (latestVersion && latestVersion !== currentVersion) {
|
||||
- markAppUpdateActionable(latestVersion)
|
||||
- const nextPopupTime = getNextAppUpdatePopupTime(latestVersion)
|
||||
- if (nextPopupTime !== null && Date.now() >= nextPopupTime) {
|
||||
- addPopupNotification({
|
||||
- contentType: 'standard',
|
||||
- title: formatMessage(updatePopupMessages.updateAvailable),
|
||||
- text: formatMessage(updatePopupMessages.linuxBody, { version: latestVersion }),
|
||||
- type: 'info',
|
||||
- autoCloseMs: null,
|
||||
- })
|
||||
- markAppUpdatePopupShown(latestVersion)
|
||||
- }
|
||||
+ const response = await fetch(`https://api.github.com/repos/${repository}/releases/latest`)
|
||||
+ if (!response.ok) return
|
||||
+ const release = await response.json()
|
||||
+
|
||||
+ // v1.2.3 is the first release of an upstream version, v1.2.3-2 the next.
|
||||
+ const match = /^v?(\d+)\.(\d+)\.(\d+)(?:-(\d+))?$/.exec(release?.tag_name ?? '')
|
||||
+ if (!match) return
|
||||
+ const latest = [...match.slice(1, 4).map(Number), Number(match[4] ?? 1)]
|
||||
+ const current = [...currentVersion.split('.').map(Number), currentRevision]
|
||||
+ const differs = latest.findIndex((part, i) => part !== current[i])
|
||||
+ if (differs === -1 || latest[differs] < current[differs]) return
|
||||
+
|
||||
+ const latestVersion = release.tag_name.replace(/^v/, '')
|
||||
+ markAppUpdateActionable(latestVersion)
|
||||
+ const nextPopupTime = getNextAppUpdatePopupTime(latestVersion)
|
||||
+ if (nextPopupTime !== null && Date.now() >= nextPopupTime) {
|
||||
+ addPopupNotification({
|
||||
+ contentType: 'standard',
|
||||
+ title: formatMessage(updatePopupMessages.updateAvailable),
|
||||
+ text: formatMessage(updatePopupMessages.linuxBody, { version: latestVersion }),
|
||||
+ type: 'info',
|
||||
+ autoCloseMs: null,
|
||||
+ buttons: [
|
||||
+ {
|
||||
+ label: formatMessage(updatePopupMessages.openRelease),
|
||||
+ action: () => openUrl(release.html_url),
|
||||
+ color: 'brand',
|
||||
+ },
|
||||
+ ],
|
||||
+ })
|
||||
+ markAppUpdatePopupShown(latestVersion)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to check for updates:', e)
|
||||
diff --git a/apps/app/src/main.rs b/apps/app/src/main.rs
|
||||
index 5cdab91..1deb12f 100644
|
||||
--- a/apps/app/src/main.rs
|
||||
+++ b/apps/app/src/main.rs
|
||||
@@ -77,6 +77,25 @@ fn is_dev() -> bool {
|
||||
fn are_updates_enabled() -> bool {
|
||||
cfg!(feature = "updater")
|
||||
&& env::var("MODRINTH_EXTERNAL_UPDATE_PROVIDER").is_err()
|
||||
+ // On Linux the updater replaces the AppImage it runs from. A .deb or
|
||||
+ // .rpm install gets the notice pointing at the release instead.
|
||||
+ && (!cfg!(target_os = "linux") || env::var_os("APPIMAGE").is_some())
|
||||
+}
|
||||
+
|
||||
+/// Which release of the upstream version this build is: 2 for v1.2.3-2. The
|
||||
+/// version itself stays the upstream one, since installers refuse a suffix.
|
||||
+#[tauri::command]
|
||||
+fn app_revision() -> u64 {
|
||||
+ option_env!("MODRINTH_ENHANCED_REVISION")
|
||||
+ .and_then(|revision| revision.parse().ok())
|
||||
+ .unwrap_or(1)
|
||||
+}
|
||||
+
|
||||
+/// The repository this build takes its updates from.
|
||||
+#[tauri::command]
|
||||
+fn release_repository() -> &'static str {
|
||||
+ option_env!("MODRINTH_ENHANCED_REPOSITORY")
|
||||
+ .unwrap_or("Felitendo/Modrinth-Enhanced")
|
||||
}
|
||||
|
||||
#[cfg(feature = "updater")]
|
||||
@@ -187,6 +206,17 @@ fn main() {
|
||||
HeaderValue::from_str(&launcher_user_agent()).unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
+ // A release carries its revision as build metadata, 1.2.3+2,
|
||||
+ // which version ordering ignores.
|
||||
+ .default_version_comparator(|current, release| {
|
||||
+ let remote = release.version;
|
||||
+ let ours = (current.major, current.minor, current.patch);
|
||||
+ let theirs = (remote.major, remote.minor, remote.patch);
|
||||
+ if theirs != ours {
|
||||
+ return theirs > ours;
|
||||
+ }
|
||||
+ remote.build.as_str().parse().unwrap_or(1) > app_revision()
|
||||
+ })
|
||||
.build(),
|
||||
);
|
||||
}
|
||||
@@ -303,6 +333,8 @@ fn main() {
|
||||
initialize_state,
|
||||
is_dev,
|
||||
are_updates_enabled,
|
||||
+ app_revision,
|
||||
+ release_repository,
|
||||
get_update_size,
|
||||
enqueue_update_for_installation,
|
||||
remove_enqueued_update,
|
||||
diff --git a/apps/app/tauri.conf.json b/apps/app/tauri.conf.json
|
||||
index e5bbabe..bd2434d 100644
|
||||
--- a/apps/app/tauri.conf.json
|
||||
+++ b/apps/app/tauri.conf.json
|
||||
@@ -102,7 +102,7 @@
|
||||
"capabilities": ["ads", "core", "plugins"],
|
||||
"csp": {
|
||||
"default-src": "'self' customprotocol: asset:",
|
||||
- "connect-src": "ipc: http://ipc.localhost https://modrinth.com https://*.modrinth.com https://*.nodes.modrinth.com https://api.mclo.gs http://textures.minecraft.net https://textures.minecraft.net https://js.stripe.com https://*.stripe.com wss://*.stripe.com https://*.intercom.io wss://*.intercom.io https://*.intercomcdn.com https://www.intercom-reporting.com wss://*.nodes.modrinth.com https://*.taila228c5.ts.net https://*.taila228c5.ts.net wss://*.taila228c5.ts.net https://fill.papermc.io https://api.purpurmc.org 'self' data: blob:",
|
||||
+ "connect-src": "ipc: http://ipc.localhost https://modrinth.com https://*.modrinth.com https://*.nodes.modrinth.com https://api.mclo.gs http://textures.minecraft.net https://textures.minecraft.net https://js.stripe.com https://*.stripe.com wss://*.stripe.com https://*.intercom.io wss://*.intercom.io https://*.intercomcdn.com https://www.intercom-reporting.com wss://*.nodes.modrinth.com https://*.taila228c5.ts.net https://*.taila228c5.ts.net wss://*.taila228c5.ts.net https://fill.papermc.io https://api.purpurmc.org https://api.github.com 'self' data: blob:",
|
||||
"font-src": ["https://cdn.modrinth.com/fonts/", "https://js.intercomcdn.com"],
|
||||
"img-src": "https: 'unsafe-inline' 'self' asset: http://asset.localhost http://textures.minecraft.net blob: data:",
|
||||
"style-src": "'unsafe-inline' 'self'",
|
||||
+43
-1
@@ -56,6 +56,47 @@ Darwin)
|
||||
;;
|
||||
esac
|
||||
|
||||
# The repository releases come from, which the app's update notice points at.
|
||||
export MODRINTH_ENHANCED_REPOSITORY="${GITHUB_REPOSITORY:-$(git -C "$REPO_ROOT" remote get-url origin | sed -E 's#^.*github\.com[:/]##; s#\.git$##')}"
|
||||
|
||||
# Updates come from this repository's own releases, signed with its own key
|
||||
# (the public half is updater.pub). A build without the private key, such as
|
||||
# one for a pull request or a local one, has nothing to sign them with and
|
||||
# leaves the updater out.
|
||||
if [ -n "${TAURI_SIGNING_PRIVATE_KEY:-}" ]; then
|
||||
repository="$MODRINTH_ENHANCED_REPOSITORY"
|
||||
updater_conf="$REPO_ROOT/build/updater.conf.json"
|
||||
mkdir -p "$(dirname "$updater_conf")"
|
||||
node -e '
|
||||
const fs = require("fs")
|
||||
const [conf, pubkey, repository] = process.argv.slice(1)
|
||||
const { capabilities } = JSON.parse(fs.readFileSync(conf, "utf8")).app.security
|
||||
console.log(JSON.stringify({
|
||||
bundle: { createUpdaterArtifacts: true },
|
||||
build: { features: ["updater"] },
|
||||
app: { security: { capabilities: [...capabilities, "updater"] } },
|
||||
plugins: {
|
||||
updater: {
|
||||
pubkey: fs.readFileSync(pubkey, "utf8").trim(),
|
||||
endpoints: [`https://github.com/${repository}/releases/latest/download/latest.json`],
|
||||
windows: { installMode: "passive" },
|
||||
},
|
||||
},
|
||||
}, null, "\t"))
|
||||
' "$WORKTREE/apps/app/tauri.conf.json" "$REPO_ROOT/updater.pub" "$repository" >"$updater_conf"
|
||||
tauri_args+=(--config "$updater_conf")
|
||||
# Tauri asks for the password when none is set, which fails without a
|
||||
# terminal. The project's key has none.
|
||||
export TAURI_SIGNING_PRIVATE_KEY_PASSWORD="${TAURI_SIGNING_PRIVATE_KEY_PASSWORD-}"
|
||||
log "Updates will come from github.com/$repository"
|
||||
else
|
||||
warn "TAURI_SIGNING_PRIVATE_KEY is not set, so this build has no updater"
|
||||
fi
|
||||
|
||||
# Which release of this upstream version this is, for the updater to tell
|
||||
# v1.2.3-2 from v1.2.3, since the app's own version cannot carry it.
|
||||
export MODRINTH_ENHANCED_REVISION="${MODRINTH_ENHANCED_REVISION:-1}"
|
||||
|
||||
# Emptied before the build, not after it: a build that fails halfway would
|
||||
# otherwise leave the previous run's installers sitting here, where
|
||||
# scripts/check.sh would happily pass them off as this build's output.
|
||||
@@ -80,7 +121,8 @@ while IFS= read -r -d '' artifact; do
|
||||
found=1
|
||||
done < <(find "$bundle_dir" -maxdepth 2 -type f \
|
||||
\( -name '*.AppImage' -o -name '*.deb' -o -name '*.rpm' \
|
||||
-o -name '*.dmg' -o -name '*.app.tar.gz' -o -name '*-setup.exe' \) -print0)
|
||||
-o -name '*.dmg' -o -name '*.app.tar.gz' -o -name '*-setup.exe' \
|
||||
-o -name '*.sig' \) -print0)
|
||||
|
||||
[ "$found" = 1 ] || die "No bundles were produced under $bundle_dir"
|
||||
|
||||
|
||||
@@ -34,6 +34,17 @@ missing() {
|
||||
! grep -qrF "$2" "$1"
|
||||
}
|
||||
|
||||
# Every installer the updater can take has its signature next to it.
|
||||
signed() {
|
||||
local artifact found=0
|
||||
for artifact in "$1"/*.AppImage "$1"/*-setup.exe "$1"/*.app.tar.gz; do
|
||||
[ -e "$artifact" ] || continue
|
||||
[ -s "$artifact.sig" ] || return 1
|
||||
found=1
|
||||
done
|
||||
[ "$found" = 1 ]
|
||||
}
|
||||
|
||||
log "Branding"
|
||||
check "tauri.conf.json is named Modrinth Enhanced" \
|
||||
contains "$WORKTREE/apps/app/tauri.conf.json" '"productName": "Modrinth Enhanced"'
|
||||
@@ -169,6 +180,12 @@ check "file pickers use the desktop portal on Linux" \
|
||||
check "NVIDIA under Wayland does not crash the webview" \
|
||||
contains "$WORKTREE/apps/app/src/main.rs" 'set_var("WEBKIT_DMABUF_RENDERER_FORCE_SHM", "1")'
|
||||
|
||||
log "Updates"
|
||||
check "updates do not come from Modrinth" \
|
||||
missing "$WORKTREE/apps/app-frontend/src/App.vue" 'launcher-files.modrinth.com/updates.json'
|
||||
check "the updater tells revisions apart" \
|
||||
contains "$WORKTREE/apps/app/src/main.rs" 'default_version_comparator'
|
||||
|
||||
log "No advertising or upsells"
|
||||
check "no Modrinth+ upsell in the app" \
|
||||
missing "$WORKTREE/apps/app-frontend/src/App.vue" "modrinth.plus"
|
||||
@@ -218,6 +235,9 @@ if [ -d "$artifacts" ] && [ -n "$(ls -A "$artifacts" 2>/dev/null)" ]; then
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if [ -n "${TAURI_SIGNING_PRIVATE_KEY:-}" ]; then
|
||||
check "the installers are signed for the updater" signed "$artifacts"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$failures" -gt 0 ]; then
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDY1Nzc2MEZBMkQyQkRGQjkKUldTNTN5c3QrbUIzWlk1RHdYTFFBMStjM29zQkZ4MW5ibHZGb2p6ckxFK0JUNDBJTkZ6RXc3NUMK
|
||||
Reference in new issue
Block a user