mirror of
https://github.com/storytold/designcraft.git
synced 2026-10-24 02:06:54 -06:00
packaging: harden shell scripts (SonarCloud S7688/S7679/S7682/S131) (#1640)
- Use bash's [[ ]] instead of [ ] for conditional tests (S7688). - Copy positional parameters into named locals in render(), has() and sha256() (S7679). - End the env.sh helper functions with an explicit return, which keeps the last command's status (S7682). - Give the appimagetool checksum case a default branch for architectures without a pinned download (S131). No behaviour change; shellcheck -x is clean.
This commit is contained in:
+12
-7
@@ -19,10 +19,11 @@ workspace_version() {
|
|||||||
/^\[/ { in_pkg = ($0 == "[workspace.package]") ; next }
|
/^\[/ { in_pkg = ($0 == "[workspace.package]") ; next }
|
||||||
in_pkg && $1 == "version" { gsub(/[" ]/, "", $3); print $3; exit }
|
in_pkg && $1 == "version" { gsub(/[" ]/, "", $3); print $3; exit }
|
||||||
' "$ROOT/Cargo.toml"
|
' "$ROOT/Cargo.toml"
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
VERSION="${DESIGNCRAFT_VERSION:-$(workspace_version)}"
|
VERSION="${DESIGNCRAFT_VERSION:-$(workspace_version)}"
|
||||||
if [ -z "$VERSION" ]; then
|
if [[ -z "$VERSION" ]]; then
|
||||||
echo "error: could not read [workspace.package] version from $ROOT/Cargo.toml" >&2
|
echo "error: could not read [workspace.package] version from $ROOT/Cargo.toml" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -32,7 +33,7 @@ DIST="${DIST:-$ROOT/dist/release}"
|
|||||||
mkdir -p "$DIST"
|
mkdir -p "$DIST"
|
||||||
export DIST
|
export DIST
|
||||||
|
|
||||||
if [ -z "${DESIGNCRAFT_BUILD_SHA:-}" ]; then
|
if [[ -z "${DESIGNCRAFT_BUILD_SHA:-}" ]]; then
|
||||||
DESIGNCRAFT_BUILD_SHA="$(git -C "$ROOT" rev-parse HEAD 2>/dev/null || true)"
|
DESIGNCRAFT_BUILD_SHA="$(git -C "$ROOT" rev-parse HEAD 2>/dev/null || true)"
|
||||||
fi
|
fi
|
||||||
export DESIGNCRAFT_BUILD_SHA
|
export DESIGNCRAFT_BUILD_SHA
|
||||||
@@ -41,29 +42,33 @@ export CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-$ROOT/target}"
|
|||||||
|
|
||||||
# Emit a GitHub Actions warning (plain stderr outside Actions).
|
# Emit a GitHub Actions warning (plain stderr outside Actions).
|
||||||
warn() {
|
warn() {
|
||||||
if [ -n "${GITHUB_ACTIONS:-}" ]; then echo "::warning::$*"; else echo "warning: $*" >&2; fi
|
if [[ -n "${GITHUB_ACTIONS:-}" ]]; then echo "::warning::$*"; else echo "warning: $*" >&2; fi
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
# Copy licence and readme files that exist into a package directory.
|
# Copy licence and readme files that exist into a package directory.
|
||||||
copy_docs() {
|
copy_docs() {
|
||||||
local dest="$1" f
|
local dest="$1" f
|
||||||
for f in README.md LICENSE LICENSE-MIT LICENSE-APACHE COPYRIGHT; do
|
for f in README.md LICENSE LICENSE-MIT LICENSE-APACHE COPYRIGHT; do
|
||||||
if [ -f "$ROOT/$f" ]; then cp "$ROOT/$f" "$dest/"; fi
|
if [[ -f "$ROOT/$f" ]]; then cp "$ROOT/$f" "$dest/"; fi
|
||||||
done
|
done
|
||||||
copy_font_licences "$dest"
|
copy_font_licences "$dest"
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
# Builds made with craft-fonts (CRAFT_FONTS_DIR, set by the release workflow) embed its fonts, so
|
# Builds made with craft-fonts (CRAFT_FONTS_DIR, set by the release workflow) embed its fonts, so
|
||||||
# the package carries their licences as OFL-<family-dir>.txt. Nothing without CRAFT_FONTS_DIR.
|
# the package carries their licences as OFL-<family-dir>.txt. Nothing without CRAFT_FONTS_DIR.
|
||||||
copy_font_licences() {
|
copy_font_licences() {
|
||||||
local dest="$1" f
|
local dest="$1" f
|
||||||
[ -n "${CRAFT_FONTS_DIR:-}" ] || return 0
|
[[ -n "${CRAFT_FONTS_DIR:-}" ]] || return 0
|
||||||
for f in "$CRAFT_FONTS_DIR"/fonts/*/OFL.txt; do
|
for f in "$CRAFT_FONTS_DIR"/fonts/*/OFL.txt; do
|
||||||
if [ -f "$f" ]; then cp "$f" "$dest/OFL-$(basename "$(dirname "$f")").txt"; fi
|
if [[ -f "$f" ]]; then cp "$f" "$dest/OFL-$(basename "$(dirname "$f")").txt"; fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
# Portable SHA-256 of a file (prints just the hash).
|
# Portable SHA-256 of a file (prints just the hash).
|
||||||
sha256() {
|
sha256() {
|
||||||
if command -v sha256sum >/dev/null; then sha256sum "$1" | cut -d' ' -f1; else shasum -a 256 "$1" | cut -d' ' -f1; fi
|
local file="$1"
|
||||||
|
if command -v sha256sum >/dev/null; then sha256sum "$file" | cut -d' ' -f1; else shasum -a 256 "$file" | cut -d' ' -f1; fi
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ APP_ID=ai.storyteller.designcraft
|
|||||||
|
|
||||||
SKIP_BUILD=0
|
SKIP_BUILD=0
|
||||||
DRY_RUN=0
|
DRY_RUN=0
|
||||||
while [ $# -gt 0 ]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--skip-build) SKIP_BUILD=1; shift ;;
|
--skip-build) SKIP_BUILD=1; shift ;;
|
||||||
--dry-run) DRY_RUN=1; SKIP_BUILD=1; shift ;;
|
--dry-run) DRY_RUN=1; SKIP_BUILD=1; shift ;;
|
||||||
@@ -36,7 +36,7 @@ case "$MACHINE" in
|
|||||||
arm64 | aarch64) ARCH=aarch64 ;;
|
arm64 | aarch64) ARCH=aarch64 ;;
|
||||||
*) echo "unsupported architecture $MACHINE" >&2; exit 2 ;;
|
*) echo "unsupported architecture $MACHINE" >&2; exit 2 ;;
|
||||||
esac
|
esac
|
||||||
if [ "$DRY_RUN" = 0 ] && [ "$(uname -s)" != FreeBSD ]; then
|
if [[ "$DRY_RUN" = 0 ]] && [[ "$(uname -s)" != FreeBSD ]]; then
|
||||||
echo "error: build on FreeBSD (or pass --dry-run to check the tree layout)" >&2
|
echo "error: build on FreeBSD (or pass --dry-run to check the tree layout)" >&2
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
@@ -46,7 +46,7 @@ echo "==> DesignCraft $VERSION for FreeBSD $ARCH"
|
|||||||
|
|
||||||
# The release VM has 12 GB; full parallelism on the biggest crates runs it out of memory.
|
# The release VM has 12 GB; full parallelism on the biggest crates runs it out of memory.
|
||||||
export CARGO_BUILD_JOBS="${CARGO_BUILD_JOBS:-4}"
|
export CARGO_BUILD_JOBS="${CARGO_BUILD_JOBS:-4}"
|
||||||
if [ "$SKIP_BUILD" = 0 ]; then
|
if [[ "$SKIP_BUILD" = 0 ]]; then
|
||||||
(cd "$ROOT" && cargo build --release --locked -p designcraft -p designcraft-cli)
|
(cd "$ROOT" && cargo build --release --locked -p designcraft -p designcraft-cli)
|
||||||
fi
|
fi
|
||||||
WORK="$CARGO_TARGET_DIR/freebsd-package"
|
WORK="$CARGO_TARGET_DIR/freebsd-package"
|
||||||
@@ -56,7 +56,7 @@ mkdir -p "$WORK"
|
|||||||
|
|
||||||
BIN="$CARGO_TARGET_DIR/release"
|
BIN="$CARGO_TARGET_DIR/release"
|
||||||
OUT_DIR="$DIST"
|
OUT_DIR="$DIST"
|
||||||
if [ "$DRY_RUN" = 1 ]; then
|
if [[ "$DRY_RUN" = 1 ]]; then
|
||||||
# Stub binaries, and the tarball stays in the work dir so dist/ only ever holds real builds.
|
# Stub binaries, and the tarball stays in the work dir so dist/ only ever holds real builds.
|
||||||
BIN="$WORK/stub-bin"
|
BIN="$WORK/stub-bin"
|
||||||
OUT_DIR="$WORK"
|
OUT_DIR="$WORK"
|
||||||
@@ -81,13 +81,13 @@ sed -e "s/@VERSION@/$VERSION/g" -e "s/@DATE@/$DESIGNCRAFT_BUILD_DATE/g" \
|
|||||||
cp -R "$ROOT/assets/app-icon/hicolor" "$STAGE/share/icons/"
|
cp -R "$ROOT/assets/app-icon/hicolor" "$STAGE/share/icons/"
|
||||||
copy_docs "$STAGE/share/doc/designcraft"
|
copy_docs "$STAGE/share/doc/designcraft"
|
||||||
for f in NOTICE ATTRIBUTION.md; do
|
for f in NOTICE ATTRIBUTION.md; do
|
||||||
if [ -f "$ROOT/$f" ]; then install -m 644 "$ROOT/$f" "$STAGE/share/doc/designcraft/"; fi
|
if [[ -f "$ROOT/$f" ]]; then install -m 644 "$ROOT/$f" "$STAGE/share/doc/designcraft/"; fi
|
||||||
done
|
done
|
||||||
|
|
||||||
for f in bin/designcraft bin/designcraft-cli "share/applications/$APP_ID.desktop" \
|
for f in bin/designcraft bin/designcraft-cli "share/applications/$APP_ID.desktop" \
|
||||||
"share/icons/hicolor/256x256/apps/$APP_ID.png" "share/icons/hicolor/scalable/apps/$APP_ID.svg" \
|
"share/icons/hicolor/256x256/apps/$APP_ID.png" "share/icons/hicolor/scalable/apps/$APP_ID.svg" \
|
||||||
share/doc/designcraft/LICENSE-MIT share/doc/designcraft/LICENSE-APACHE; do
|
share/doc/designcraft/LICENSE-MIT share/doc/designcraft/LICENSE-APACHE; do
|
||||||
if [ ! -e "$STAGE/$f" ]; then echo "error: $f is missing from the package" >&2; exit 1; fi
|
if [[ ! -e "$STAGE/$f" ]]; then echo "error: $f is missing from the package" >&2; exit 1; fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# ---- .tar.gz ------------------------------------------------------------------------------------
|
# ---- .tar.gz ------------------------------------------------------------------------------------
|
||||||
@@ -96,7 +96,7 @@ tar -C "$WORK" -czf "$OUT_DIR/$BASENAME.tar.gz" "$BASENAME"
|
|||||||
echo "wrote $OUT_DIR/$BASENAME.tar.gz"
|
echo "wrote $OUT_DIR/$BASENAME.tar.gz"
|
||||||
|
|
||||||
"$STAGE/bin/designcraft-cli" --version
|
"$STAGE/bin/designcraft-cli" --version
|
||||||
if [ "$DRY_RUN" = 1 ]; then
|
if [[ "$DRY_RUN" = 1 ]]; then
|
||||||
echo "==> dry run: tarball contents"
|
echo "==> dry run: tarball contents"
|
||||||
tar -tzvf "$OUT_DIR/$BASENAME.tar.gz"
|
tar -tzvf "$OUT_DIR/$BASENAME.tar.gz"
|
||||||
fi
|
fi
|
||||||
|
|||||||
+4
-1
@@ -21,7 +21,10 @@ MAC="$TMP/mac.svg"
|
|||||||
sed 's/viewBox="0 0 512 512"/viewBox="-62.136 -62.136 636.272 636.272"/' "$SVG" >"$MAC"
|
sed 's/viewBox="0 0 512 512"/viewBox="-62.136 -62.136 636.272 636.272"/' "$SVG" >"$MAC"
|
||||||
grep -q 'viewBox="-62.136' "$MAC" || { echo "error: expected viewBox=\"0 0 512 512\" in $SVG" >&2; exit 1; }
|
grep -q 'viewBox="-62.136' "$MAC" || { echo "error: expected viewBox=\"0 0 512 512\" in $SVG" >&2; exit 1; }
|
||||||
|
|
||||||
render() { resvg -w "$2" -h "$2" "$1" "$3" </dev/null; }
|
render() {
|
||||||
|
local svg="$1" size="$2" out="$3"
|
||||||
|
resvg -w "$size" -h "$size" "$svg" "$out" </dev/null
|
||||||
|
}
|
||||||
|
|
||||||
render "$SVG" 1024 "$DIR/designcraft-1024.png"
|
render "$SVG" 1024 "$DIR/designcraft-1024.png"
|
||||||
# Runtime window/Dock icon on macOS (embedded by apps/designcraft); other platforms use hicolor 256.
|
# Runtime window/Dock icon on macOS (embedded by apps/designcraft); other platforms use hicolor 256.
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ FLATHUB=https://dl.flathub.org/repo/flathub.flatpakrepo
|
|||||||
|
|
||||||
TEST=1
|
TEST=1
|
||||||
TARBALL=""
|
TARBALL=""
|
||||||
while [ $# -gt 0 ]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--no-test) TEST=0; shift ;;
|
--no-test) TEST=0; shift ;;
|
||||||
-h | --help) sed -n '2,14p' "$0"; exit 0 ;;
|
-h | --help) sed -n '2,14p' "$0"; exit 0 ;;
|
||||||
@@ -38,7 +38,7 @@ case "$ARCH" in
|
|||||||
esac
|
esac
|
||||||
BASENAME="designcraft-$VERSION-linux-$ARCH"
|
BASENAME="designcraft-$VERSION-linux-$ARCH"
|
||||||
TARBALL="${TARBALL:-$DIST/$BASENAME.tar.gz}"
|
TARBALL="${TARBALL:-$DIST/$BASENAME.tar.gz}"
|
||||||
[ -f "$TARBALL" ] || { echo "error: $TARBALL not found (run packaging/linux/package.sh --formats tar first)" >&2; exit 1; }
|
[[ -f "$TARBALL" ]] || { echo "error: $TARBALL not found (run packaging/linux/package.sh --formats tar first)" >&2; exit 1; }
|
||||||
for tool in flatpak flatpak-builder; do
|
for tool in flatpak flatpak-builder; do
|
||||||
command -v "$tool" >/dev/null || { echo "error: $tool not found (apt install flatpak flatpak-builder librsvg2-common)" >&2; exit 1; }
|
command -v "$tool" >/dev/null || { echo "error: $tool not found (apt install flatpak flatpak-builder librsvg2-common)" >&2; exit 1; }
|
||||||
done
|
done
|
||||||
@@ -49,7 +49,7 @@ WORK="$CARGO_TARGET_DIR/flatpak-bundle"
|
|||||||
rm -rf "$WORK"
|
rm -rf "$WORK"
|
||||||
mkdir -p "$WORK/stage"
|
mkdir -p "$WORK/stage"
|
||||||
tar -xzf "$TARBALL" -C "$WORK/stage" --strip-components=1
|
tar -xzf "$TARBALL" -C "$WORK/stage" --strip-components=1
|
||||||
[ -x "$WORK/stage/bin/designcraft" ] || { echo "error: $TARBALL has no bin/designcraft" >&2; exit 1; }
|
[[ -x "$WORK/stage/bin/designcraft" ]] || { echo "error: $TARBALL has no bin/designcraft" >&2; exit 1; }
|
||||||
cp "$HERE/flatpak/$APP_ID.bundle.yml" "$WORK/$APP_ID.yml"
|
cp "$HERE/flatpak/$APP_ID.bundle.yml" "$WORK/$APP_ID.yml"
|
||||||
|
|
||||||
flatpak remote-add --user --if-not-exists flathub "$FLATHUB"
|
flatpak remote-add --user --if-not-exists flathub "$FLATHUB"
|
||||||
@@ -62,7 +62,7 @@ OUT="$DIST/$BASENAME.flatpak"
|
|||||||
flatpak build-bundle --runtime-repo="$FLATHUB" "$WORK/repo" "$OUT" "$APP_ID" stable
|
flatpak build-bundle --runtime-repo="$FLATHUB" "$WORK/repo" "$OUT" "$APP_ID" stable
|
||||||
echo "wrote $OUT"
|
echo "wrote $OUT"
|
||||||
|
|
||||||
if [ "$TEST" = 1 ]; then
|
if [[ "$TEST" = 1 ]]; then
|
||||||
flatpak install --user -y --noninteractive --reinstall "$OUT"
|
flatpak install --user -y --noninteractive --reinstall "$OUT"
|
||||||
flatpak info --user "$APP_ID"
|
flatpak info --user "$APP_ID"
|
||||||
flatpak run --command=designcraft-cli "$APP_ID" --version
|
flatpak run --command=designcraft-cli "$APP_ID" --version
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ APP_ID=ai.storyteller.designcraft
|
|||||||
|
|
||||||
SKIP_BUILD=0
|
SKIP_BUILD=0
|
||||||
FORMATS="appimage deb rpm arch tar"
|
FORMATS="appimage deb rpm arch tar"
|
||||||
while [ $# -gt 0 ]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--skip-build) SKIP_BUILD=1; shift ;;
|
--skip-build) SKIP_BUILD=1; shift ;;
|
||||||
--formats) FORMATS="$2"; shift 2 ;;
|
--formats) FORMATS="$2"; shift 2 ;;
|
||||||
@@ -43,8 +43,8 @@ BASENAME="designcraft-$VERSION-linux-$ARCH"
|
|||||||
|
|
||||||
echo "==> DesignCraft $VERSION for Linux $ARCH ($FORMATS)"
|
echo "==> DesignCraft $VERSION for Linux $ARCH ($FORMATS)"
|
||||||
|
|
||||||
if [ "$SKIP_BUILD" = 0 ]; then
|
if [[ "$SKIP_BUILD" = 0 ]]; then
|
||||||
if [ -n "${CROSS_TARGET:-}" ]; then
|
if [[ -n "${CROSS_TARGET:-}" ]]; then
|
||||||
(cd "$ROOT" && cargo build --release --locked -p designcraft -p designcraft-cli --target "$CROSS_TARGET")
|
(cd "$ROOT" && cargo build --release --locked -p designcraft -p designcraft-cli --target "$CROSS_TARGET")
|
||||||
else
|
else
|
||||||
(cd "$ROOT" && cargo build --release --locked -p designcraft -p designcraft-cli)
|
(cd "$ROOT" && cargo build --release --locked -p designcraft -p designcraft-cli)
|
||||||
@@ -76,7 +76,10 @@ if command -v appstreamcli >/dev/null; then
|
|||||||
appstreamcli validate --no-net --explain "$STAGE/usr/share/metainfo/$APP_ID.metainfo.xml"
|
appstreamcli validate --no-net --explain "$STAGE/usr/share/metainfo/$APP_ID.metainfo.xml"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
has() { case " $FORMATS " in *" $1 "*) return 0 ;; *) return 1 ;; esac; }
|
has() {
|
||||||
|
local fmt="$1"
|
||||||
|
case " $FORMATS " in *" $fmt "*) return 0 ;; *) return 1 ;; esac
|
||||||
|
}
|
||||||
|
|
||||||
# ---- .tar.gz ------------------------------------------------------------------------------------
|
# ---- .tar.gz ------------------------------------------------------------------------------------
|
||||||
if has tar; then
|
if has tar; then
|
||||||
@@ -134,6 +137,8 @@ if has appimage; then
|
|||||||
case "$ARCH" in
|
case "$ARCH" in
|
||||||
x86_64) APPIMAGETOOL_SHA256=ed4ce84f0d9caff66f50bcca6ff6f35aae54ce8135408b3fa33abfc3cb384eb0 ;;
|
x86_64) APPIMAGETOOL_SHA256=ed4ce84f0d9caff66f50bcca6ff6f35aae54ce8135408b3fa33abfc3cb384eb0 ;;
|
||||||
aarch64) APPIMAGETOOL_SHA256=f0837e7448a0c1e4e650a93bb3e85802546e60654ef287576f46c71c126a9158 ;;
|
aarch64) APPIMAGETOOL_SHA256=f0837e7448a0c1e4e650a93bb3e85802546e60654ef287576f46c71c126a9158 ;;
|
||||||
|
# No pinned download (e.g. riscv64): set APPIMAGETOOL or put appimagetool on PATH.
|
||||||
|
*) APPIMAGETOOL_SHA256="" ;;
|
||||||
esac
|
esac
|
||||||
APPDIR="$WORK/DesignCraft.AppDir"
|
APPDIR="$WORK/DesignCraft.AppDir"
|
||||||
cp -R "$STAGE" "$APPDIR"
|
cp -R "$STAGE" "$APPDIR"
|
||||||
@@ -144,9 +149,9 @@ if has appimage; then
|
|||||||
ln -s "$APP_ID.png" "$APPDIR/.DirIcon"
|
ln -s "$APP_ID.png" "$APPDIR/.DirIcon"
|
||||||
|
|
||||||
TOOL="${APPIMAGETOOL:-$(command -v appimagetool || true)}"
|
TOOL="${APPIMAGETOOL:-$(command -v appimagetool || true)}"
|
||||||
if [ -z "$TOOL" ]; then
|
if [[ -z "$TOOL" ]]; then
|
||||||
TOOL="$CARGO_TARGET_DIR/appimagetool-$APPIMAGETOOL_VERSION-$ARCH.AppImage"
|
TOOL="$CARGO_TARGET_DIR/appimagetool-$APPIMAGETOOL_VERSION-$ARCH.AppImage"
|
||||||
if [ ! -x "$TOOL" ]; then
|
if [[ ! -x "$TOOL" ]]; then
|
||||||
download="$TOOL.download"
|
download="$TOOL.download"
|
||||||
curl --proto '=https' -fsSL -o "$download" \
|
curl --proto '=https' -fsSL -o "$download" \
|
||||||
"https://github.com/AppImage/appimagetool/releases/download/$APPIMAGETOOL_VERSION/appimagetool-$ARCH.AppImage"
|
"https://github.com/AppImage/appimagetool/releases/download/$APPIMAGETOOL_VERSION/appimagetool-$ARCH.AppImage"
|
||||||
@@ -174,16 +179,16 @@ if has appimage; then
|
|||||||
# package) appimagetool also writes the .zsync, into its working directory, hence the cd.
|
# package) appimagetool also writes the .zsync, into its working directory, hence the cd.
|
||||||
(cd "$DIST" && ARCH="$ARCH" APPIMAGE_EXTRACT_AND_RUN=1 "$TOOL" --no-appstream -u "$UPDATE_INFO" "$APPDIR" "$OUT")
|
(cd "$DIST" && ARCH="$ARCH" APPIMAGE_EXTRACT_AND_RUN=1 "$TOOL" --no-appstream -u "$UPDATE_INFO" "$APPDIR" "$OUT")
|
||||||
echo "wrote $OUT"
|
echo "wrote $OUT"
|
||||||
if [ -s "$OUT.zsync" ]; then
|
if [[ -s "$OUT.zsync" ]]; then
|
||||||
echo "wrote $OUT.zsync"
|
echo "wrote $OUT.zsync"
|
||||||
else
|
else
|
||||||
warn "zsyncmake not found, so $OUT.zsync was not written; AppImage delta updates need it"
|
warn "zsyncmake not found, so $OUT.zsync was not written; AppImage delta updates need it"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "${CROSS_TARGET:-}" ]; then
|
if [[ -z "${CROSS_TARGET:-}" ]]; then
|
||||||
"$STAGE/usr/bin/designcraft-cli" --version
|
"$STAGE/usr/bin/designcraft-cli" --version
|
||||||
elif [ -n "${EMULATOR:-}" ]; then
|
elif [[ -n "${EMULATOR:-}" ]]; then
|
||||||
"$EMULATOR" "$STAGE/usr/bin/designcraft-cli" --version
|
"$EMULATOR" "$STAGE/usr/bin/designcraft-cli" --version
|
||||||
fi
|
fi
|
||||||
echo "==> done"
|
echo "==> done"
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ umask 077
|
|||||||
# shellcheck source=../env.sh
|
# shellcheck source=../env.sh
|
||||||
. "$(dirname "${BASH_SOURCE[0]}")/../env.sh"
|
. "$(dirname "${BASH_SOURCE[0]}")/../env.sh"
|
||||||
|
|
||||||
if [ -z "${APPLE_CERTIFICATE:-}" ]; then
|
if [[ -z "${APPLE_CERTIFICATE:-}" ]]; then
|
||||||
warn "APPLE_CERTIFICATE is not set: macOS builds will be ad-hoc signed and not notarized"
|
warn "APPLE_CERTIFICATE is not set: macOS builds will be ad-hoc signed and not notarized"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
@@ -36,13 +36,13 @@ security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KC_PASS"
|
|||||||
security list-keychains -d user -s "$KEYCHAIN" $(security list-keychains -d user | tr -d '"')
|
security list-keychains -d user -s "$KEYCHAIN" $(security list-keychains -d user | tr -d '"')
|
||||||
|
|
||||||
IDENTITY="$(security find-identity -v -p codesigning "$KEYCHAIN" | awk '/Developer ID Application/ { print $2; exit }')"
|
IDENTITY="$(security find-identity -v -p codesigning "$KEYCHAIN" | awk '/Developer ID Application/ { print $2; exit }')"
|
||||||
if [ -z "$IDENTITY" ]; then
|
if [[ -z "$IDENTITY" ]]; then
|
||||||
security find-identity -v -p codesigning "$KEYCHAIN" >&2
|
security find-identity -v -p codesigning "$KEYCHAIN" >&2
|
||||||
echo "error: no 'Developer ID Application' identity in APPLE_CERTIFICATE" >&2
|
echo "error: no 'Developer ID Application' identity in APPLE_CERTIFICATE" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo "Imported signing identity $IDENTITY"
|
echo "Imported signing identity $IDENTITY"
|
||||||
if [ -n "${GITHUB_ENV:-}" ]; then
|
if [[ -n "${GITHUB_ENV:-}" ]]; then
|
||||||
{ echo "MACOS_SIGN_IDENTITY=$IDENTITY"; echo "MACOS_KEYCHAIN=$KEYCHAIN"; } >>"$GITHUB_ENV"
|
{ echo "MACOS_SIGN_IDENTITY=$IDENTITY"; echo "MACOS_KEYCHAIN=$KEYCHAIN"; } >>"$GITHUB_ENV"
|
||||||
else
|
else
|
||||||
echo "MACOS_SIGN_IDENTITY=$IDENTITY"
|
echo "MACOS_SIGN_IDENTITY=$IDENTITY"
|
||||||
|
|||||||
+12
-12
@@ -19,7 +19,7 @@ HERE="$ROOT/packaging/macos"
|
|||||||
|
|
||||||
ARCH=universal
|
ARCH=universal
|
||||||
SKIP_BUILD=0
|
SKIP_BUILD=0
|
||||||
while [ $# -gt 0 ]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--arch) ARCH="$2"; shift 2 ;;
|
--arch) ARCH="$2"; shift 2 ;;
|
||||||
--skip-build) SKIP_BUILD=1; shift ;;
|
--skip-build) SKIP_BUILD=1; shift ;;
|
||||||
@@ -44,9 +44,9 @@ DMG="$DIST/designcraft-$VERSION-macos-$ARCH.dmg"
|
|||||||
CLI_ZIP="$DIST/designcraft-cli-$VERSION-macos-$ARCH.zip"
|
CLI_ZIP="$DIST/designcraft-cli-$VERSION-macos-$ARCH.zip"
|
||||||
|
|
||||||
NOTARIZE=0
|
NOTARIZE=0
|
||||||
if [ "$IDENTITY" = "-" ]; then
|
if [[ "$IDENTITY" = "-" ]]; then
|
||||||
warn "macOS: ad-hoc signing (no MACOS_SIGN_IDENTITY); artifacts are not notarized"
|
warn "macOS: ad-hoc signing (no MACOS_SIGN_IDENTITY); artifacts are not notarized"
|
||||||
elif [ -n "${APPLE_ID:-}" ] && [ -n "${APPLE_PASSWORD:-}" ] && [ -n "${APPLE_TEAM_ID:-}" ]; then
|
elif [[ -n "${APPLE_ID:-}" ]] && [[ -n "${APPLE_PASSWORD:-}" ]] && [[ -n "${APPLE_TEAM_ID:-}" ]]; then
|
||||||
NOTARIZE=1
|
NOTARIZE=1
|
||||||
else
|
else
|
||||||
warn "macOS: APPLE_ID / APPLE_PASSWORD / APPLE_TEAM_ID incomplete; signed but not notarized"
|
warn "macOS: APPLE_ID / APPLE_PASSWORD / APPLE_TEAM_ID incomplete; signed but not notarized"
|
||||||
@@ -55,7 +55,7 @@ fi
|
|||||||
echo "==> DesignCraft $VERSION for macOS ($ARCH), identity: $IDENTITY, notarize: $NOTARIZE"
|
echo "==> DesignCraft $VERSION for macOS ($ARCH), identity: $IDENTITY, notarize: $NOTARIZE"
|
||||||
|
|
||||||
# ---- build -------------------------------------------------------------------------------------
|
# ---- build -------------------------------------------------------------------------------------
|
||||||
if [ "$SKIP_BUILD" = 0 ]; then
|
if [[ "$SKIP_BUILD" = 0 ]]; then
|
||||||
args=()
|
args=()
|
||||||
for t in "${TARGETS[@]}"; do args+=(--target "$t"); done
|
for t in "${TARGETS[@]}"; do args+=(--target "$t"); done
|
||||||
(cd "$ROOT" && cargo build --release --locked -p designcraft -p designcraft-cli "${args[@]}")
|
(cd "$ROOT" && cargo build --release --locked -p designcraft -p designcraft-cli "${args[@]}")
|
||||||
@@ -74,9 +74,9 @@ done
|
|||||||
sign() {
|
sign() {
|
||||||
# Hardened runtime + secure timestamp for a real identity; ad-hoc can't be timestamped.
|
# Hardened runtime + secure timestamp for a real identity; ad-hoc can't be timestamped.
|
||||||
local ts=(--timestamp)
|
local ts=(--timestamp)
|
||||||
[ "$IDENTITY" = "-" ] && ts=(--timestamp=none)
|
[[ "$IDENTITY" = "-" ]] && ts=(--timestamp=none)
|
||||||
local kc=()
|
local kc=()
|
||||||
[ -n "${MACOS_KEYCHAIN:-}" ] && kc=(--keychain "$MACOS_KEYCHAIN")
|
[[ -n "${MACOS_KEYCHAIN:-}" ]] && kc=(--keychain "$MACOS_KEYCHAIN")
|
||||||
codesign --force --sign "$IDENTITY" ${kc[@]+"${kc[@]}"} "${ts[@]}" "$@"
|
codesign --force --sign "$IDENTITY" ${kc[@]+"${kc[@]}"} "${ts[@]}" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,8 +88,8 @@ notarize() {
|
|||||||
echo "$out"
|
echo "$out"
|
||||||
id="$(printf '%s' "$out" | plutil -extract id raw -o - - 2>/dev/null || true)"
|
id="$(printf '%s' "$out" | plutil -extract id raw -o - - 2>/dev/null || true)"
|
||||||
status="$(printf '%s' "$out" | plutil -extract status raw -o - - 2>/dev/null || true)"
|
status="$(printf '%s' "$out" | plutil -extract status raw -o - - 2>/dev/null || true)"
|
||||||
if [ "$status" != "Accepted" ]; then
|
if [[ "$status" != "Accepted" ]]; then
|
||||||
if [ -n "$id" ]; then
|
if [[ -n "$id" ]]; then
|
||||||
xcrun notarytool log "$id" --apple-id "$APPLE_ID" --password "$APPLE_PASSWORD" --team-id "$APPLE_TEAM_ID" || true
|
xcrun notarytool log "$id" --apple-id "$APPLE_ID" --password "$APPLE_PASSWORD" --team-id "$APPLE_TEAM_ID" || true
|
||||||
fi
|
fi
|
||||||
echo "error: notarization of $(basename "$file") failed (status: ${status:-unknown})" >&2
|
echo "error: notarization of $(basename "$file") failed (status: ${status:-unknown})" >&2
|
||||||
@@ -117,7 +117,7 @@ sign --options runtime --entitlements "$HERE/entitlements.plist" "$APP/Contents/
|
|||||||
sign --options runtime --entitlements "$HERE/entitlements.plist" "$APP"
|
sign --options runtime --entitlements "$HERE/entitlements.plist" "$APP"
|
||||||
codesign --verify --strict --deep --verbose=2 "$APP"
|
codesign --verify --strict --deep --verbose=2 "$APP"
|
||||||
|
|
||||||
if [ "$NOTARIZE" = 1 ]; then
|
if [[ "$NOTARIZE" = 1 ]]; then
|
||||||
ditto -c -k --keepParent "$APP" "$WORK/DesignCraft-notarize.zip"
|
ditto -c -k --keepParent "$APP" "$WORK/DesignCraft-notarize.zip"
|
||||||
notarize "$WORK/DesignCraft-notarize.zip"
|
notarize "$WORK/DesignCraft-notarize.zip"
|
||||||
xcrun stapler staple "$APP"
|
xcrun stapler staple "$APP"
|
||||||
@@ -151,7 +151,7 @@ hdiutil_retry() {
|
|||||||
if hdiutil "$@"; then
|
if hdiutil "$@"; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
[ "$attempt" = 5 ] && { echo "hdiutil $what failed 5 times" >&2; return 1; }
|
[[ "$attempt" = 5 ]] && { echo "hdiutil $what failed 5 times" >&2; return 1; }
|
||||||
echo "hdiutil $what failed (attempt $attempt of 5); retrying in $((attempt * 10))s" >&2
|
echo "hdiutil $what failed (attempt $attempt of 5); retrying in $((attempt * 10))s" >&2
|
||||||
sleep $((attempt * 10))
|
sleep $((attempt * 10))
|
||||||
done
|
done
|
||||||
@@ -169,7 +169,7 @@ if ! codesign --verify --strict --deep --verbose=2 "$MOUNT/DesignCraft.app"; the
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
hdiutil_retry detach detach "$MOUNT" >/dev/null
|
hdiutil_retry detach detach "$MOUNT" >/dev/null
|
||||||
if [ "$NOTARIZE" = 1 ]; then
|
if [[ "$NOTARIZE" = 1 ]]; then
|
||||||
notarize "$DMG"
|
notarize "$DMG"
|
||||||
xcrun stapler staple "$DMG"
|
xcrun stapler staple "$DMG"
|
||||||
xcrun stapler validate "$DMG"
|
xcrun stapler validate "$DMG"
|
||||||
@@ -187,7 +187,7 @@ codesign --verify --strict --verbose=2 "$CLI_DIR/designcraft-cli"
|
|||||||
rm -f "$CLI_ZIP"
|
rm -f "$CLI_ZIP"
|
||||||
ditto -c -k --keepParent "$CLI_DIR" "$CLI_ZIP"
|
ditto -c -k --keepParent "$CLI_DIR" "$CLI_ZIP"
|
||||||
# A bare Mach-O can't carry a stapled ticket; Gatekeeper looks the notarization up online.
|
# A bare Mach-O can't carry a stapled ticket; Gatekeeper looks the notarization up online.
|
||||||
if [ "$NOTARIZE" = 1 ]; then notarize "$CLI_ZIP"; fi
|
if [[ "$NOTARIZE" = 1 ]]; then notarize "$CLI_ZIP"; fi
|
||||||
|
|
||||||
"$WORK/bin/designcraft-cli" --version
|
"$WORK/bin/designcraft-cli" --version
|
||||||
echo "==> done"
|
echo "==> done"
|
||||||
|
|||||||
@@ -11,13 +11,13 @@ set -euo pipefail
|
|||||||
. "$(dirname "${BASH_SOURCE[0]}")/../env.sh"
|
. "$(dirname "${BASH_SOURCE[0]}")/../env.sh"
|
||||||
HERE="$ROOT/packaging/web"
|
HERE="$ROOT/packaging/web"
|
||||||
|
|
||||||
if [ "${1:-}" != "--skip-build" ]; then
|
if [[ "${1:-}" != "--skip-build" ]]; then
|
||||||
command -v trunk >/dev/null || { echo "error: trunk not found (cargo install trunk --locked)" >&2; exit 1; }
|
command -v trunk >/dev/null || { echo "error: trunk not found (cargo install trunk --locked)" >&2; exit 1; }
|
||||||
(cd "$ROOT/apps/designcraft-web" && trunk build --release)
|
(cd "$ROOT/apps/designcraft-web" && trunk build --release)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
SITE="$ROOT/dist/web"
|
SITE="$ROOT/dist/web"
|
||||||
[ -f "$SITE/index.html" ] || { echo "error: $SITE/index.html missing; run without --skip-build" >&2; exit 1; }
|
[[ -f "$SITE/index.html" ]] || { echo "error: $SITE/index.html missing; run without --skip-build" >&2; exit 1; }
|
||||||
# Paths must be relative so the site works under any prefix (public_url = "./" in Trunk.toml).
|
# Paths must be relative so the site works under any prefix (public_url = "./" in Trunk.toml).
|
||||||
if grep -Eq '(src|href)="/[^/]' "$SITE/index.html"; then
|
if grep -Eq '(src|href)="/[^/]' "$SITE/index.html"; then
|
||||||
echo "error: $SITE/index.html has root-absolute URLs; it would break when served from a sub-path" >&2
|
echo "error: $SITE/index.html has root-absolute URLs; it would break when served from a sub-path" >&2
|
||||||
|
|||||||
Reference in New Issue
Block a user