#!/usr/bin/env bash # Compila o Tessel do fredygames.com: Tessel 1.0.23 (GPL-3.0-or-later), de Gijs van Tulder, a partir do # tarball do commit c70d63c do repositorio gvtulder/tessel, como no "npm run build" do autor (lingui # compile + parcel build), com tres diferencas na chamada: SKIP_SERVICE_WORKER=true (o jogo nao registra service # worker nem guarda o site em cache no navegador do visitante), --public-url ./ (o jogo mora numa # subpasta) e --no-cache. Este script e o patch ao lado dele sao parte do codigo-fonte publicado junto # do jogo ("the scripts used to control compilation" da GPL). # # src/FredGames.Web/Content/games/tessel/engine/build.sh # # Node 24.21.0 (o oficial, darwin-arm64, conferido pelo SHA-256; traz o npm 11.19.0) fica em # artifacts/tools/node-v24.21.0. "npm ci" instala exatamente as versoes do package-lock.json do commit # (o npm confere a integridade de cada pacote), com o cache dentro da pasta de saida. Dois builds # seguidos dao os mesmos bytes. # # tessel-fredygames.patch: # - babel.config.js: a versao mostrada nas configuracoes leva o commit fixo (o tarball nao tem .git); # - src/index.html: sem o (instalar como app) e sem a meta apple-itunes-app # (faixa da App Store no Safari); links para outros sites abrem em outra aba (o jogo roda num # iframe, onde paginas como o GitHub nao abrem); # - src/main.browser.ts: nas paginas /pt-br/ do site o idioma padrao e o portugues do Brasil (um # idioma escolhido nas configuracoes continua valendo). # - src/main.shared.ts: o jogo nao pula para a raiz do site ("/") quando o caminho e outro (aqui ele # mora em bundles/tessel//index.html). # - src/ui/shared/icons.ts: o icone de livro (botao "How to play?") era do Font Awesome Pro, de licenca # comercial; no lugar dele vai o "book-open" do Font Awesome Free 6.7.2 (CC BY 4.0), como os demais. # # Saida: artifacts/build/tessel-1.0.23/dist/, que o bundle.yaml do jogo confere arquivo por arquivo. set -euo pipefail VERSION=1.0.23 COMMIT=c70d63cc76485389a963ab1d63cf431e2a3e9d8d SHA256=eb58c3ba032a7c31db44e3653e62ab0abd35429be33628b1baae337c3869c465 NODE=24.21.0 NODE_SHA256=bed7eea5325e1108f32ce5228ddd6a5f0f08a499ee42aa7442aea583702f6057 here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" root="$(git -C "$here" rev-parse --show-toplevel 2>/dev/null || pwd)" out="$root/artifacts/build/tessel-$VERSION" cache="$root/artifacts/build/cache" tools="$root/artifacts/tools" mkdir -p "$cache" fetch() { if [ ! -f "$cache/$2" ]; then curl -fsSL --retry 4 "$1" -o "$cache/$2.partial" && mv "$cache/$2.partial" "$cache/$2" fi echo "$3 $cache/$2" | shasum -a 256 -c - } fetch "https://github.com/gvtulder/tessel/archive/$COMMIT.tar.gz" "tessel-${COMMIT:0:7}.tar.gz" "$SHA256" fetch "https://nodejs.org/dist/v$NODE/node-v$NODE-darwin-arm64.tar.gz" "node-v$NODE-darwin-arm64.tar.gz" "$NODE_SHA256" if [ ! -d "$tools/node-v$NODE" ]; then mkdir -p "$tools/node-v$NODE.tmp" tar -xzf "$cache/node-v$NODE-darwin-arm64.tar.gz" -C "$tools/node-v$NODE.tmp" mv "$tools/node-v$NODE.tmp/node-v$NODE-darwin-arm64" "$tools/node-v$NODE" rm -rf "$tools/node-v$NODE.tmp" fi rm -rf "$out" mkdir -p "$out/tree" "$out/home" tar -xzf "$cache/tessel-${COMMIT:0:7}.tar.gz" -C "$out/tree" --strip-components 1 patch -d "$out/tree" -p1 --quiet < "$here/tessel-fredygames.patch" # Ambiente isolado: o Node fixo no PATH, o cache e a configuracao do npm dentro da pasta de saida. export PATH="$tools/node-v$NODE/bin:/usr/bin:/bin:/usr/sbin:/sbin" export HOME="$out/home" npm_config_cache="$out/home/npm-cache" npm_config_userconfig="$out/home/npmrc" export npm_config_update_notifier=false npm_config_fund=false npm_config_audit=false export TZ=UTC LC_ALL=C SOURCE_DATE_EPOCH=1782919048 cd "$out/tree" npm ci --no-progress --loglevel=error npx lingui compile --typescript NODE_ENV=production SKIP_SERVICE_WORKER=true npx parcel build src/index.html \ --no-source-maps --no-cache --public-url ./ --dist-dir "$out/dist" # Bibliotecas de node_modules que entram no game.*.js (dependencias de execucao do package.json e as # dependencias delas; o resto do package-lock.json e ferramenta de build): o fonte delas, como o npm as # instalou, vai num tarball deterministico, e as licencas num texto unico. RUNTIME_DEPS="@lingui/core @lingui/message-utils @messageformat/parser @messageformat/date-skeleton js-sha256 canonical-json check2d sat poly-decomp-es polygon-clipping robust-predicates splaytree workbox-core workbox-window workbox-precaching workbox-routing workbox-strategies @parcel/service-worker zod" /usr/bin/python3 - "$out" $RUNTIME_DEPS <<'PY' import gzip, io, os, sys, tarfile out, deps = sys.argv[1], sys.argv[2:] mtime = int(os.environ["SOURCE_DATE_EPOCH"]) base = os.path.join(out, "tree", "node_modules") raw = io.BytesIO() with tarfile.open(fileobj=raw, mode="w", format=tarfile.PAX_FORMAT) as tar: for dep in deps: files = [] for d, dirs, names in os.walk(os.path.join(base, dep)): dirs.sort() files += [os.path.join(d, n) for n in names] for f in sorted(files): info = tar.gettarinfo(f, "node_modules/" + os.path.relpath(f, base)) info.mtime, info.uid, info.gid, info.uname, info.gname = mtime, 0, 0, "", "" info.mode = 0o755 if info.mode & 0o111 else 0o644 with open(f, "rb") as fh: tar.addfile(info, fh) with open(os.path.join(out, "tessel-runtime-deps.tar.gz"), "wb") as fh: with gzip.GzipFile(fileobj=fh, mode="wb", mtime=0, filename="") as gz: gz.write(raw.getvalue()) with open(os.path.join(out, "THIRD-PARTY-LICENSES.txt"), "w") as fh: for dep in deps: d = os.path.join(base, dep) names = sorted(n for n in os.listdir(d) if n.lower().startswith(("licen", "copying", "unlicense"))) import json meta = json.load(open(os.path.join(d, "package.json"))) fh.write("=" * 78 + "\n%s %s (%s)\n" % (dep, meta["version"], meta.get("license")) + "=" * 78 + "\n\n") for n in names: fh.write(open(os.path.join(d, n), encoding="utf-8").read().rstrip() + "\n\n") if not names: fh.write("(no licence file in the package; package.json declares %s)\n\n" % meta.get("license")) PY echo "Tessel $VERSION em $out/dist:" (cd "$out/dist" && find . -type f | LC_ALL=C sort | sed 's#^\./##' | while read -r f; do echo "$(shasum -a 256 "$f" | cut -d' ' -f1) $f" done) shasum -a 256 "$out/tessel-runtime-deps.tar.gz" "$out/THIRD-PARTY-LICENSES.txt"