R7.1: bundled installers, one dmg and one setup.exe for all six apps

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-10-16 11:17:47 -04:00
1 parent e22f276c1d
commit b12858c7f0
9 files changed
+200 -21

No files matched your search

+31 -19
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
# Usage: release.sh [batch]; a dmg per app of the batch.
# Usage: release.sh [batch]; a dmg per app, one of all.
set -euo pipefail
root=$(cd "$(dirname "$0")/../.." && pwd)
@@ -12,32 +12,44 @@ releases=https://git.zacharyzhang.com/ZacharyZhang-NY/ElyOffice/releases
echo "release.sh: notarizing needs ELY_SIGN_IDENTITY, a Developer ID" >&2
exit 1
}
# Usage: dmg <out> <volume> <app>...; apps beside Applications.
dmg() {
local out=$1 volume=$2 stage
shift 2
rm -f "$out"
# Drag an app onto Applications.
stage=$(mktemp -d)
for app in "$@"; do ditto "$app" "$stage/$(basename "$app")"; done
ln -s /Applications "$stage/Applications"
hdiutil create -quiet -volname "$volume" -srcfolder "$stage" -format UDZO "$out"
rm -rf "$stage"
if [ -n "${ELY_NOTARY_PROFILE:-}" ]; then
codesign --force --timestamp --sign "$ELY_SIGN_IDENTITY" "$out"
xcrun notarytool submit "$out" --keychain-profile "$ELY_NOTARY_PROFILE" --wait
xcrun stapler staple "$out"
else
echo "release.sh: $out is not notarized (no ELY_NOTARY_PROFILE)" >&2
fi
echo "$out"
}
"$root/packaging/source.sh" "$dist"
awk -F'\t' -v batch="$batch" '$4 == batch { print $1 "\t" $2 }' "$root/packaging/apps.tsv" |
while IFS=$'\t' read -r slug name; do
"$root/packaging/macos/bundle.sh" "$slug" release
codesign --verify --deep --strict "$dist/$name.app"
dmg=$dist/$name-$version-$arch.dmg
rm -f "$dmg"
# The app beside Applications: drag one onto the other.
stage=$(mktemp -d)
ditto "$dist/$name.app" "$stage/$name.app"
ln -s /Applications "$stage/Applications"
hdiutil create -quiet -volname "$name" -srcfolder "$stage" -format UDZO "$dmg"
rm -rf "$stage"
if [ -n "${ELY_NOTARY_PROFILE:-}" ]; then
codesign --force --timestamp --sign "$ELY_SIGN_IDENTITY" "$dmg"
xcrun notarytool submit "$dmg" --keychain-profile "$ELY_NOTARY_PROFILE" --wait
xcrun stapler staple "$dmg"
else
echo "release.sh: $dmg is not notarized (no ELY_NOTARY_PROFILE)" >&2
fi
echo "$dmg"
out=$dist/$name-$version-$arch.dmg
dmg "$out" "$name" "$dist/$name.app"
# What the app's update check reads from the latest release.
sha=$(shasum -a 256 "$dmg" | cut -d' ' -f1)
url="$releases/download/v$version/$(basename "$dmg")"
sha=$(shasum -a 256 "$out" | cut -d' ' -f1)
url="$releases/download/v$version/$(basename "$out")"
printf '{"version": "%s", "assets": {"macos-%s": {"url": "%s", "sha256": "%s"}}}\n' \
"$version" "${arch/arm64/aarch64}" "$url" "$sha" >"$dist/$slug.json"
echo "$dist/$slug.json"
done
# Every app of the batch in one dmg.
apps=()
for name in $(awk -F'\t' -v batch="$batch" '$4 == batch { print $2 }' "$root/packaging/apps.tsv"); do
apps+=("$dist/$name.app")
done
dmg "$dist/ElyOffice-$version-$arch.dmg" "Ely Office" "${apps[@]}"
rm -rf "$root/target/release/incremental"
+53
View File
@@ -0,0 +1,53 @@
; Installs the ticked apps, each by its own setup.
Unicode true
!include "MUI2.nsh"
!ifndef VERSION
!error "pass -DVERSION"
!endif
!ifndef APPS
!error "pass -DAPPS, from packaging/windows/bundle.sh"
!endif
!ifndef OUTFILE
!error "pass -DOUTFILE"
!endif
Name "Ely Office ${VERSION}"
OutFile "${OUTFILE}"
RequestExecutionLevel user
; The setups inside are compressed already.
SetCompress off
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_LANGUAGE "SimpChinese"
!insertmacro MUI_LANGUAGE "English"
LangString Failed ${LANG_SIMPCHINESE} "$R0 未装上,其安装程序退出码为 $R1(2 表示文件被占用或安装位置被占)。之前装上的应用照旧可用。"
LangString Failed ${LANG_ENGLISH} "$R0 was not installed; its setup exited with $R1 (2: a file is in use or in the way). Apps installed before it work."
Function .onInit
InitPluginsDir
FunctionEnd
; One section per app; its setup runs silent.
!macro ElyApp NAME SETUP
Section "${NAME}"
SetOutPath "$PLUGINSDIR"
File "/oname=${NAME}-setup.exe" "${SETUP}"
DetailPrint "${NAME}"
StrCpy $R0 "${NAME}"
ClearErrors
ExecWait '"$PLUGINSDIR\${NAME}-setup.exe" /S' $R1
IfErrors 0 +2
StrCpy $R1 "-"
Delete "$PLUGINSDIR\${NAME}-setup.exe"
StrCmp $R1 0 ely_done_${NAME}
MessageBox MB_ICONSTOP "$(Failed)" /SD IDOK
SetErrorLevel 2
Abort
ely_done_${NAME}:
SectionEnd
!macroend
!include "${APPS}"
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
# Builds dist/ElyOffice-<version>-windows-x86_64-setup.exe from the apps' setups.
set -euo pipefail
root=$(cd "$(dirname "$0")/../.." && pwd)
dist=${ELY_DIST:-$root/dist}
version=$(awk -F'"' '/^version = / { print $2; exit }' "$root/Cargo.toml")
makensis=${MAKENSIS:-"/c/Program Files (x86)/NSIS/makensis.exe"}
[ -x "$makensis" ] || {
echo "bundle.sh: no makensis at $makensis; install NSIS" >&2
exit 1
}
apps=$root/target/stage/bundle-apps.nsh
mkdir -p "$(dirname "$apps")"
: >"$apps"
for name in $(awk -F'\t' '$4 == 1 { print $2 }' "$root/packaging/apps.tsv"); do
setup=$dist/$name-$version-windows-x86_64-setup.exe
[ -f "$setup" ] || {
echo "bundle.sh: no $setup; run installer.sh first" >&2
exit 1
}
printf '!insertmacro ElyApp "%s" "%s"\n' "$name" "$(cygpath -w "$setup")" >>"$apps"
done
out=$dist/ElyOffice-$version-windows-x86_64-setup.exe
"$makensis" -V2 -INPUTCHARSET UTF8 -DVERSION="$version" -DAPPS="$(cygpath -w "$apps")" \
-DOUTFILE="$(cygpath -w "$out")" "$(cygpath -w "$root/packaging/windows/bundle.nsi")"
echo "$out"