Files
toolbox-portal/scripts/release.sh
T
zemion d1d4b3f44e
Verify / verify (push) Canceled after 0s
Swith to v0.20.3
2026-09-03 10:31:09 +02:00

259 lines
5.9 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
cd "${PROJECT_DIR}"
usage() {
cat <<'USAGE'
Usage: scripts/release.sh [options]
Bundles the current lockfile into a portal archive and publishes the release to Gitea.
Options:
--lock PATH Lock file to use (default: release/toolbox.lock.json)
--tag TAG Release tag to create/push (default: v<releaseVersion>)
--owner OWNER Gitea owner/org (default: lotobo)
--repo REPO Gitea repository (default: toolbox-portal)
--api-base URL Gitea API base URL (default: https://git.add-ideas.de/api/v1)
--remote REMOTE Git remote used to push the tag (default: origin)
--build-dir DIR Build directory (default: build)
--output-subdir DIR Assembled output directory under build-dir (default: toolbox)
--skip-tests Skip npm test
--skip-assemble Skip npm run assemble
--skip-build Skip npm run build
--skip-tag Skip tagging/push of the release tag
--skip-git-push Skip pushing git branch and tag
--skip-publish Skip Gitea release publish/upload
--force Force overwrite of build outputs
--dry-run Print commands without running remote publishing operations
--help Show this help
Environment:
GITEA_TOKEN Personal token for Gitea API calls
GITEA_API_BASE Optional override for API base URL
Examples:
scripts/release.sh
scripts/release.sh --tag v0.20.4 --skip-tests
USAGE
}
LOCK_FILE="release/toolbox.lock.json"
OWNER="lotobo"
REPO="toolbox-portal"
API_BASE="${GITEA_API_BASE:-https://git.add-ideas.de/api/v1}"
REMOTE="origin"
BUILD_DIR="build"
OUTPUT_SUBDIR="toolbox"
SKIP_TESTS=0
SKIP_ASSEMBLE=0
SKIP_BUILD=0
SKIP_TAG=0
SKIP_GIT_PUSH=0
SKIP_PUBLISH=0
FORCE=0
DRY_RUN=0
while [ "$#" -gt 0 ]; do
case "$1" in
--lock)
LOCK_FILE="$2"
shift 2
;;
--tag)
TAG_OVERRIDE="$2"
shift 2
;;
--owner)
OWNER="$2"
shift 2
;;
--repo)
REPO="$2"
shift 2
;;
--api-base)
API_BASE="$2"
shift 2
;;
--remote)
REMOTE="$2"
shift 2
;;
--build-dir)
BUILD_DIR="$2"
shift 2
;;
--output-subdir)
OUTPUT_SUBDIR="$2"
shift 2
;;
--skip-tests)
SKIP_TESTS=1
shift
;;
--skip-assemble)
SKIP_ASSEMBLE=1
shift
;;
--skip-build)
SKIP_BUILD=1
shift
;;
--skip-tag)
SKIP_TAG=1
shift
;;
--skip-git-push)
SKIP_GIT_PUSH=1
shift
;;
--skip-publish)
SKIP_PUBLISH=1
shift
;;
--force)
FORCE=1
shift
;;
--dry-run)
DRY_RUN=1
shift
;;
--help|-h)
usage
exit 0
;;
*)
echo "Unknown argument: $1" >&2
usage
exit 1
;;
esac
done
run() {
if [ "$DRY_RUN" -eq 1 ]; then
echo "DRY-RUN: $*"
return 0
fi
"$@"
}
RELEASE_VERSION="$(node -e "const fs=require('fs');const path=process.argv[1];const lock=JSON.parse(fs.readFileSync(path,'utf8'));if(!lock?.releaseVersion){process.exit(1);}console.log(lock.releaseVersion);" "$LOCK_FILE")"
if [ -z "$RELEASE_VERSION" ]; then
echo "releaseVersion could not be read from ${LOCK_FILE}" >&2
exit 1
fi
if [ -n "${TAG_OVERRIDE:-}" ]; then
RELEASE_TAG="$TAG_OVERRIDE"
else
RELEASE_TAG="v${RELEASE_VERSION}"
fi
ZIP_FILE="${BUILD_DIR}/add-ideas-toolbox-${RELEASE_VERSION}.zip"
CHECKSUM_FILE="${ZIP_FILE}.sha256"
TARGET_DIR="${BUILD_DIR}/${OUTPUT_SUBDIR}"
if [ "$SKIP_TESTS" -eq 0 ]; then
run npm test
fi
if [ "$SKIP_BUILD" -eq 0 ]; then
run npm run build
fi
if [ "$SKIP_ASSEMBLE" -eq 0 ]; then
ASSEMBLE_ARGS=(
npm
run
assemble
--
--lock
"$LOCK_FILE"
--portal-dist
dist
--output
"$TARGET_DIR"
--archive
"$ZIP_FILE"
)
if [ "$FORCE" -eq 1 ]; then
ASSEMBLE_ARGS+=(--force)
fi
run "${ASSEMBLE_ARGS[@]}"
fi
if [ ! -s "$ZIP_FILE" ]; then
echo "Release archive missing: $ZIP_FILE" >&2
exit 1
fi
if [ ! -s "$CHECKSUM_FILE" ]; then
if [ "$DRY_RUN" -eq 1 ]; then
echo "DRY-RUN: would create ${CHECKSUM_FILE}"
else
sha256sum "$ZIP_FILE" > "$CHECKSUM_FILE"
fi
fi
if [ "$SKIP_TAG" -eq 0 ]; then
if git rev-parse -q --verify "refs/tags/${RELEASE_TAG}" >/dev/null; then
CURRENT_COMMIT="$(git rev-parse "${RELEASE_TAG}^{commit}")"
HEAD_COMMIT="$(git rev-parse HEAD)"
if [ "$CURRENT_COMMIT" != "$HEAD_COMMIT" ]; then
echo "Tag ${RELEASE_TAG} already exists at ${CURRENT_COMMIT}, but HEAD is ${HEAD_COMMIT}." >&2
exit 1
fi
echo "Tag exists at HEAD: ${RELEASE_TAG}"
else
echo "Creating tag ${RELEASE_TAG}"
run git tag -a "$RELEASE_TAG" -m "toolbox ${RELEASE_TAG}"
fi
if [ "$SKIP_GIT_PUSH" -eq 0 ]; then
run git push "$REMOTE" HEAD
run git push "$REMOTE" "$RELEASE_TAG"
fi
fi
if [ "$SKIP_PUBLISH" -eq 0 ]; then
TOKEN="${GITEA_TOKEN:-}"
if [ -z "$TOKEN" ]; then
if [ -f "${HOME}/.config/gitea/gitea.env" ]; then
# shellcheck disable=SC1091
. "${HOME}/.config/gitea/gitea.env"
TOKEN="${GITEA_TOKEN:-}"
fi
fi
if [ -z "$TOKEN" ]; then
echo "GITEA_TOKEN is required for publishing (or use --skip-publish)." >&2
exit 1
fi
run node scripts/publish-release.mjs \
--api-base "$API_BASE" \
--owner "$OWNER" \
--repo "$REPO" \
--tag "$RELEASE_TAG" \
--target "$(git rev-parse HEAD)" \
--name "Toolbox ${RELEASE_TAG}" \
--archive "$ZIP_FILE" \
--checksum "$CHECKSUM_FILE" \
--lock-file "$LOCK_FILE" \
--token "$TOKEN"
if [ "$DRY_RUN" -eq 1 ]; then
echo "Dry run complete. No assets were uploaded."
else
echo "Published ${RELEASE_TAG} to Gitea."
fi
fi
echo "Release wrapper finished for ${RELEASE_TAG}"