#!/usr/bin/env bash # release-client.sh — ensure the Forgejo release for a client-v* tag # exists, upload whichever client artifacts are present in dist/, and roll # the auto-update manifest (deploy/single-node/version.yaml) forward. # # Mirrors ~/code/jiu/scripts/ci/release-client.sh's asset-guarding pattern, # but uses pangolin's own lib-forgejo.sh API (forgejo_release_ensure / # forgejo_upload_asset — different names/signature than jiu's create_release/ # upload_asset). # # Manifest handling differs from jiu on purpose: jiu's backend reads # backend/config/version.yaml straight out of its own working directory, so # rewriting that file in the repo checkout is enough. Pangolin's server reads # VERSION_MANIFEST from /etc/pangolin (see server/internal/httpapi/version.go # + deploy/single-node/deploy.sh), a path that lives on pangolin1, not in any # git checkout — so getting the new version/build_number onto the live host # needs an SSH push, the same DEPLOY_SSH_KEY / lib-ssh.sh path # deploy-client.sh already uses for the downloads/ dir (see # .gitea/workflows/deploy-client.yml, which now passes DEPLOY_SSH_KEY into # this step too). Also unlike jiu, download_urls are fixed "latest" stable # URLs (deploy-client.sh keeps only one file per platform) and changelog[] # isn't populated yet (no CHANGELOG-client.md in this repo) — so only # version/build_number are rewritten here, everything else in the manifest # template is passed through unchanged. # # Multiple platform build jobs (android/windows/...) all upload into the SAME # release, guarded by `[ -f ... ]` since a given CI run may only have built a # subset (e.g. a partial manual re-dispatch, or before macOS/iOS land). set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" # shellcheck source=scripts/ci/_env.sh . "${SCRIPT_DIR}/_env.sh" # shellcheck source=scripts/ci/lib-forgejo.sh . "${SCRIPT_DIR}/lib-forgejo.sh" # shellcheck source=scripts/ci/lib-ssh.sh . "${SCRIPT_DIR}/lib-ssh.sh" TAG="${1:?usage: release-client.sh }" ver_file="/tmp/release_client_ver.$$" ver_from_tag client "$TAG" > "$ver_file" VER="" read -r VER < "$ver_file" || true # 无结尾换行的 read 退出码,见 release-server.sh 同注释 rm -f "$ver_file" echo "==> release-client: tag=${TAG} ver=${VER}" forgejo_release_ensure "$TAG" "client ${VER}" if [ -f dist/pangolin-android.apk ]; then forgejo_upload_asset "$TAG" dist/pangolin-android.apk fi if [ -f dist/pangolin-windows-x64-setup.exe ]; then forgejo_upload_asset "$TAG" dist/pangolin-windows-x64-setup.exe fi if [ -f dist/pangolin-macos-x64.zip ]; then forgejo_upload_asset "$TAG" dist/pangolin-macos-x64.zip fi # iOS has no dist/ artifact — compile-ios.sh uploads straight to TestFlight # via altool (matches jiu), nothing to attach to the Forgejo release here. # ── Auto-update manifest: bump version/build_number, stage + push to pangolin1 ── # BUILD is derived the exact same way compile-android.sh derives the APK's # Android versionCode (major*10000 + minor*100 + patch) so the manifest's # build_number stays consistent with the shipped APK for a given tag, rather # than being an independently-incremented counter like jiu's. MAJOR="${VER%%.*}" _REST="${VER#*.}" MINOR="${_REST%%.*}" PATCH="${_REST#*.}" PATCH="${PATCH%%-*}" BUILD=$(( MAJOR * 10000 + MINOR * 100 + PATCH )) MANIFEST_TMPL="${REPO_ROOT}/deploy/single-node/version.yaml" MANIFEST_OUT="/tmp/pangolin_version_manifest.$$.yaml" if [ -f "$MANIFEST_TMPL" ]; then : > "$MANIFEST_OUT" while IFS= read -r line || [ -n "$line" ]; do case "$line" in version:*) printf 'version: "%s"\n' "$VER" >> "$MANIFEST_OUT" ;; build_number:*) printf 'build_number: %d\n' "$BUILD" >> "$MANIFEST_OUT" ;; *) printf '%s\n' "$line" >> "$MANIFEST_OUT" ;; esac done < "$MANIFEST_TMPL" mkdir -p dist cp "$MANIFEST_OUT" dist/version.yaml # Stage as a release asset too, so a manual rollback can re-fetch the exact # manifest that shipped alongside this tag (mirrors jiu's rationale). forgejo_upload_asset "$TAG" dist/version.yaml if [ -n "${DEPLOY_SSH_KEY:-}" ]; then echo "==> release-client: pushing version.yaml (version=${VER} build_number=${BUILD}) to pangolin1" setup_ssh SCP="scp -i ${SSH_KEY_FILE} -P ${DEPLOY_PORT} -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=${SSH_KNOWN_HOSTS_FILE}" $SSH "root@${DEPLOY_HOST}" "mkdir -p /etc/pangolin" $SCP "$MANIFEST_OUT" "root@${DEPLOY_HOST}:/tmp/pangolin_version.yaml.new" $SSH "root@${DEPLOY_HOST}" "mv /tmp/pangolin_version.yaml.new /etc/pangolin/version.yaml && chown pangolin:pangolin /etc/pangolin/version.yaml && chmod 644 /etc/pangolin/version.yaml" echo "==> release-client: version.yaml deployed to pangolin1 (/etc/pangolin/version.yaml)" else echo "==> release-client: DEPLOY_SSH_KEY not set — skipping live manifest push (dist/version.yaml still staged + uploaded as a release asset)" fi rm -f "$MANIFEST_OUT" else echo "==> release-client: WARN manifest template ${MANIFEST_TMPL} not found — skipping version.yaml update" >&2 fi echo "==> release-client: done — Release ${TAG} updated. dist/ contents:" ls -lh dist/ 2>/dev/null || true