Something went wrong. Try again.
Data management tools for playing BattleTech
Something went wrong. Try again.
Shell
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238#!/usr/bin/env bash# Build helm's browser artifacts and put them in the assets bucket.## AWS_PROFILE=lance-blue scripts/deploy.sh 0.51.0# scripts/deploy.sh 0.51.0 --dry-run## One command: fetch the MegaMek release if it is not already unpacked, run the# bridge dump if there is not already one for it, build the binary and the# wasm, write the index and the catalogue, upload, and record the release id.# Both the install and the dump are cached under ~/.cache/helm, so the second# run of the day skips straight to the build.## --megamek and --bridge-dir override either half when you have one already.## Three files, under one prefix named after this commit:## <ref>/helm_wasm.wasm the rules, compiled for a browser# <ref>/<megamek>/units.json which designs there are, and where the rest is# <ref>/<megamek>/<chunk>.json one group of columns each, named by units.json# <ref>/<megamek>/equipment.json every name MegaMek answers to, for search# <ref>/<megamek>/catalogue.jsonl the equipment the rules read## https://lance.blue/assets/helm/<ref>/<megamek>/units.json## Two levels because the artifacts are functions of two things. The wasm is# this repository's code alone; the index and the catalogue are this code over# a particular MegaMek. Keyed by one of them only, a rebuild silently replaces# a file somebody is already fetching - which is what an immutable cache# header promises does not happen.## Nothing is ever overwritten, so nothing is ever invalidated: a new build is a# new prefix. What decides which prefix the site fetches is releases.helm in# infra, which this writes and an apply serves - the same shape headquarters# and arena deploy in, and this script does not apply anything.## INFRA_DIR overrides where the infra checkout is; the default is the sibling# directory.set -euo pipefail
cd "$(dirname "$0")/.."
version=""megamek=""bridge=""dry_run=""while [ $# -gt 0 ]; do case "$1" in --megamek) megamek="${2:?--megamek needs a path}" shift 2 ;; --bridge-dir) bridge="${2:?--bridge-dir needs a path}" shift 2 ;; -n | --dry-run) dry_run=1 shift ;; -h | --help) echo "usage: scripts/deploy.sh <megamek-version> [--dry-run]" echo " [--megamek <install>] [--bridge-dir <dump>]" exit 0 ;; -*) echo "deploy: unknown argument $1" >&2 exit 2 ;; *) version="$1" shift ;; esacdone
# Everything below fails before anything is fetched or built.if [ -z "$version" ] && { [ -z "$megamek" ] || [ -z "$bridge" ]; }; then echo "deploy: which MegaMek? scripts/deploy.sh 0.51.0" >&2 exit 2fi# Before anything is fetched, dumped or built. A cold run is a 600MB download,# two minutes of JVM and two cargo builds, and finding out after all of it that# the login expired is the whole reason this is up here. A dry run uploads# nothing, so it needs none of it.if [ -z "$dry_run" ]; then : "${AWS_PROFILE:?set AWS_PROFILE; default credentials are almost never the right account}"
# The variable being set says nothing about the session behind it. if ! aws sts get-caller-identity --query Account --output text >/dev/null; then echo "deploy: no working AWS session for profile $AWS_PROFILE; log in again" >&2 exit 1 fifi
command -v jq >/dev/null || { echo "deploy: jq is not installed; it writes releases.auto.tfvars.json" >&2 exit 1}command -v aws >/dev/null || { echo "deploy: the aws cli is not installed" >&2 exit 1}
if ! infra="$(cd "${INFRA_DIR:-../infra}" 2>/dev/null && pwd)"; then echo "deploy: no infra checkout at ${INFRA_DIR:-../infra}; set INFRA_DIR" >&2 exit 1fitfvars="$infra/envs/lance.blue/releases.auto.tfvars.json"[ -f "$tfvars" ] || { echo "deploy: $infra has no envs/lance.blue/releases.auto.tfvars.json" >&2 exit 1}
# A dirty tree gets a -dirty ref, which names a build nobody else can rebuild.if [ -n "$(git status --porcelain)" ]; then echo "deploy: helm has uncommitted changes; commit or stash them" >&2 exit 1fi
# Deploying off a branch is fine - the branch is part of the ref, so what is# serving is legible from the id alone. main is the one branch with a rule,# and the remote is asked rather than whatever the last fetch left behind.branch=$(git rev-parse --abbrev-ref HEAD)if [ "$branch" = main ]; then git fetch --quiet origin main if [ "$(git rev-parse HEAD)" != "$(git rev-parse origin/main)" ]; then echo "deploy: on main, but HEAD is not origin/main; pull or push first" >&2 exit 1 fifi
ref="${BUILD_REF:-$(scripts/build-ref.sh)}"
echo "deploy: $ref"
# The install. fetch-megamek.sh caches the tarball and skips an unpack it has# already done, so this is a no-op after the first run.if [ -z "$megamek" ]; then megamek="$(scripts/fetch-megamek.sh "$version")"fi
# The dump. Cached per MegaMek version rather than per run: it is two minutes# of JVM and its inputs are a release that never changes and bridge/, which# changes rarely. Delete the directory to force a fresh one.if [ -z "$bridge" ]; then bridge="${XDG_CACHE_HOME:-$HOME/.cache}/helm/bridge/${version:-unknown}" if [ -f "$bridge/equipment.jsonl" ]; then echo "using the dump in $bridge" else mkdir -p "$bridge" ./bridge/dump.sh "$megamek" "$bridge" fifi[ -f "$bridge/equipment.jsonl" ] || { echo "deploy: no equipment.jsonl in $bridge; the dump did not finish" >&2 exit 1}cargo build --release -p helm-cli -j 2cargo build --release -p helm-wasm --target wasm32-unknown-unknown -j 2
out="$(mktemp -d)"trap 'rm -rf "$out" "$tfvars.new"' EXIT
# The MegaMek version is read from the install rather than passed, for the same# reason `helm build` reads it: a flag that can be typed wrong is a provenance# hole, and this one decides which prefix the artifacts land under../target/release/helm index \ --megamek "$megamek" \ --bridge-dir "$bridge" \ --helm-version "$ref" \ --out "$out/units.json"
# From the build block, which is also what says this index and the loadout# beside it are about the same designs.mm="$(grep -o '"megamek":"[^"]*"' "$out/units.json" | head -1 | cut -d'"' -f4)"[ -n "$mm" ] || { echo "deploy: the index names no MegaMek version" >&2 exit 1}
# The catalogue the rules read in a browser, slimmed to the fields they use../target/release/helm catalogue --bridge-dir "$bridge" --out "$out/catalogue.jsonl"cp target/wasm32-unknown-unknown/release/helm_wasm.wasm "$out/helm_wasm.wasm"
echo# Every chunk the index names, so a chunk added in helm is published without# this script learning its name.chunks="$(jq -r '.chunks[]' "$out/units.json") equipment.json"for file in units.json $chunks catalogue.jsonl helm_wasm.wasm; do [ -f "$out/$file" ] || { echo "deploy: units.json names $file and helm did not write it" >&2 exit 1 } printf ' %-16s %6s KB\n' "$file" "$(( $(wc -c <"$out/$file") / 1024 ))"doneecho
if [ -n "$dry_run" ]; then echo "dry run: would publish under $ref/$mm; $tfvars not touched" exit 0fi
bucket="$(tofu -chdir="$infra/envs/lance.blue" output -raw assets_helm_bucket)"
# Immutable because a prefix is written once: the ref names this commit and# the MegaMek version names that release, so the same path can only ever hold# the same bytes.cache="public, max-age=31536000, immutable"aws s3 cp "$out/helm_wasm.wasm" "s3://$bucket/$ref/helm_wasm.wasm" \ --content-type application/wasm --cache-control "$cache" --no-progressaws s3 cp "$out/units.json" "s3://$bucket/$ref/$mm/units.json" \ --content-type application/json --cache-control "$cache" --no-progressfor file in $chunks; do aws s3 cp "$out/$file" "s3://$bucket/$ref/$mm/$file" \ --content-type application/json --cache-control "$cache" --no-progressdoneaws s3 cp "$out/catalogue.jsonl" "s3://$bucket/$ref/$mm/catalogue.jsonl" \ --content-type application/x-ndjson --cache-control "$cache" --no-progress
# Written beside the file it replaces so the move is atomic; a jq that fails# halfway leaves the current release id in place.jq --arg ref "$ref" '.releases.helm = $ref' "$tfvars" >"$tfvars.new"mv "$tfvars.new" "$tfvars"
echoecho "Published under $ref/$mm:"echo " https://lance.blue/assets/helm/$ref/helm_wasm.wasm"echo " https://lance.blue/assets/helm/$ref/$mm/units.json"for file in $chunks; do echo " https://lance.blue/assets/helm/$ref/$mm/$file"doneecho " https://lance.blue/assets/helm/$ref/$mm/catalogue.jsonl"echoecho "Wrote releases.helm = $ref"echo "To serve it:"echo " tofu -chdir=$infra/envs/lance.blue plan -out=lance.blue.tfplan"echo " tofu -chdir=$infra/envs/lance.blue apply lance.blue.tfplan"