- Replace all .gitea/workflows with GitHub Actions equivalents - test.yml: port full Gitea pipeline (rust-test + frontend-test jobs) using ghcr.io/msicie/trcaa-linux-amd64:rust1.88-node22; triggers on main and feature/bug/fix branches plus PRs targeting main - release.yml: port auto-tag pipeline; switch to GITHUB_TOKEN + gh CLI for tagging, changelog, and artifact uploads; add macos-13 Intel build job alongside macos-latest ARM64; replace wiki sync to point at GitHub wiki; all master refs updated to main - build-images.yml: switch registry from local Gitea to ghcr.io/msicie, login with GITHUB_TOKEN - Delete pr-review.yml (qwen3-coder-next replaced by native Copilot review) - Add .github/CODEOWNERS with @Shaun-Arman-VFK387_moto + @github-copilot - Update Makefile: replace Gogs API/repo refs with gh CLI for uploads - Update CLAUDE.md: wiki URL, CI/CD section, branch refs (master→main)
510 lines
18 KiB
YAML
510 lines
18 KiB
YAML
name: Release
|
|
|
|
# Runs on every merge to main — reads the latest semver tag, increments
|
|
# the patch version, pushes a new tag, generates a changelog, then builds
|
|
# multi-platform release artifacts and uploads them to GitHub Releases.
|
|
# workflow_dispatch allows manual triggering.
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
workflow_dispatch:
|
|
|
|
concurrency:
|
|
group: release-main
|
|
cancel-in-progress: false
|
|
|
|
permissions:
|
|
contents: write
|
|
packages: read
|
|
|
|
jobs:
|
|
autotag:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
release_tag: ${{ steps.bump.outputs.release_tag }}
|
|
steps:
|
|
- name: Checkout (full history + all tags)
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Configure git
|
|
run: |
|
|
git config user.name "github-actions[bot]"
|
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
|
|
- name: Bump patch version and create tag
|
|
id: bump
|
|
run: |
|
|
set -eu
|
|
|
|
# Read the version declared in Cargo.toml
|
|
CARGO_VERSION=$(grep '^version' src-tauri/Cargo.toml | head -1 | sed 's/version = "//;s/"//')
|
|
CARGO_TAG="v${CARGO_VERSION}"
|
|
echo "Cargo.toml declares: $CARGO_TAG"
|
|
|
|
# Get the latest clean semver tag (vX.Y.Z only)
|
|
LATEST=$(git tag --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1 || echo "")
|
|
echo "Latest git tag: ${LATEST:-none}"
|
|
|
|
# Version resolution:
|
|
# 1. Cargo.toml > latest tag → use Cargo.toml (major/minor bump)
|
|
# 2. Cargo.toml == latest tag → reuse for builds (already tagged)
|
|
# 3. Cargo.toml < latest tag → auto-increment patch on latest tag
|
|
if [ -z "$LATEST" ]; then
|
|
NEXT="$CARGO_TAG"
|
|
elif [ "$(printf '%s\n' "$LATEST" "$CARGO_TAG" | sort -V | tail -1)" = "$CARGO_TAG" ]; then
|
|
NEXT="$CARGO_TAG"
|
|
if [ "$CARGO_TAG" = "$LATEST" ]; then
|
|
echo "Cargo.toml matches latest tag — reusing $NEXT for builds"
|
|
else
|
|
echo "Cargo.toml version $CARGO_TAG is ahead of $LATEST — using Cargo.toml"
|
|
fi
|
|
else
|
|
MAJOR=$(echo "$LATEST" | cut -d. -f1 | tr -d 'v')
|
|
MINOR=$(echo "$LATEST" | cut -d. -f2)
|
|
PATCH=$(echo "$LATEST" | cut -d. -f3)
|
|
NEXT="v${MAJOR}.${MINOR}.$((PATCH + 1))"
|
|
fi
|
|
|
|
echo "Latest tag: ${LATEST:-none} → Next: $NEXT"
|
|
|
|
if git ls-remote --exit-code --tags origin "refs/tags/$NEXT" >/dev/null 2>&1; then
|
|
echo "Tag $NEXT already exists; builds will target this tag."
|
|
else
|
|
git tag -a "$NEXT" -m "Release $NEXT"
|
|
git push origin "refs/tags/$NEXT"
|
|
echo "Tag $NEXT pushed successfully"
|
|
fi
|
|
|
|
echo "release_tag=$NEXT" >> "$GITHUB_OUTPUT"
|
|
|
|
changelog:
|
|
needs: autotag
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout (full history + all tags)
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Configure git
|
|
run: |
|
|
git config user.name "github-actions[bot]"
|
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
|
|
- name: Install git-cliff
|
|
run: |
|
|
set -eu
|
|
CLIFF_VER="2.7.0"
|
|
curl -fsSL \
|
|
"https://github.com/orhun/git-cliff/releases/download/v${CLIFF_VER}/git-cliff-${CLIFF_VER}-x86_64-unknown-linux-musl.tar.gz" \
|
|
| tar -xz --strip-components=1 -C /usr/local/bin \
|
|
"git-cliff-${CLIFF_VER}/git-cliff"
|
|
|
|
- name: Generate changelog
|
|
env:
|
|
RELEASE_TAG: ${{ needs.autotag.outputs.release_tag }}
|
|
run: |
|
|
set -eu
|
|
CURRENT_TAG="${RELEASE_TAG}"
|
|
echo "Building changelog for $CURRENT_TAG"
|
|
|
|
if ! git rev-parse "refs/tags/${CURRENT_TAG}" >/dev/null 2>&1; then
|
|
echo "ERROR: tag ${CURRENT_TAG} not found locally after fetch"
|
|
exit 1
|
|
fi
|
|
|
|
git-cliff --config cliff.toml --output CHANGELOG.md
|
|
PREV_TAG=$(git tag --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \
|
|
| grep -v "^${CURRENT_TAG}$" | head -1 || echo "")
|
|
if [ -n "$PREV_TAG" ]; then
|
|
git-cliff --config cliff.toml --tag "$CURRENT_TAG" --strip all > /tmp/release_body.md || true
|
|
else
|
|
echo "No previous tag found, generating from git commits"
|
|
git log --pretty=format:"- %s" > /tmp/release_body.md || true
|
|
fi
|
|
echo "=== Release body preview ==="
|
|
cat /tmp/release_body.md
|
|
|
|
- name: Create or update GitHub release
|
|
env:
|
|
RELEASE_TAG: ${{ needs.autotag.outputs.release_tag }}
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
set -eu
|
|
TAG="${RELEASE_TAG}"
|
|
BODY=$(cat /tmp/release_body.md)
|
|
|
|
if gh release view "$TAG" >/dev/null 2>&1; then
|
|
echo "Updating existing release $TAG..."
|
|
gh release edit "$TAG" --notes "$BODY"
|
|
echo "✓ Release body updated"
|
|
else
|
|
echo "Creating release $TAG..."
|
|
gh release create "$TAG" \
|
|
--title "TFTSR $TAG" \
|
|
--notes "$BODY"
|
|
echo "✓ Release created"
|
|
fi
|
|
|
|
- name: Commit CHANGELOG.md to main
|
|
env:
|
|
RELEASE_TAG: ${{ needs.autotag.outputs.release_tag }}
|
|
run: |
|
|
set -euo pipefail
|
|
TAG="${RELEASE_TAG}"
|
|
if ! echo "$TAG" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
|
|
echo "ERROR: Unexpected tag format: $TAG"
|
|
exit 1
|
|
fi
|
|
git add CHANGELOG.md
|
|
if git diff --staged --quiet; then
|
|
echo "No CHANGELOG.md changes to commit"
|
|
else
|
|
git commit -m "chore: update CHANGELOG.md for ${TAG} [skip ci]"
|
|
git push origin HEAD:main
|
|
echo "✓ CHANGELOG.md committed to main"
|
|
fi
|
|
|
|
- name: Upload CHANGELOG.md as release asset
|
|
env:
|
|
RELEASE_TAG: ${{ needs.autotag.outputs.release_tag }}
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
set -eu
|
|
TAG="${RELEASE_TAG}"
|
|
# Remove existing asset if present to allow re-upload
|
|
gh release delete-asset "$TAG" CHANGELOG.md --yes 2>/dev/null || true
|
|
gh release upload "$TAG" CHANGELOG.md
|
|
echo "✓ CHANGELOG.md uploaded"
|
|
|
|
wiki-sync:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 1
|
|
|
|
- name: Configure git
|
|
run: |
|
|
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
git config --global user.name "github-actions[bot]"
|
|
|
|
- name: Clone and sync wiki
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
cd /tmp
|
|
WIKI_URL="https://x-access-token:${GH_TOKEN}@github.com/msicie/apollo_nxt-trcaa.wiki.git"
|
|
|
|
if ! git clone "$WIKI_URL" wiki 2>/dev/null; then
|
|
echo "Wiki doesn't exist yet, creating initial structure..."
|
|
mkdir -p wiki
|
|
cd wiki
|
|
git init
|
|
git checkout -b master
|
|
echo "# Wiki" > Home.md
|
|
git add Home.md
|
|
git commit -m "Initial wiki commit"
|
|
git remote add origin "$WIKI_URL"
|
|
fi
|
|
|
|
cd /tmp/wiki
|
|
if [ -d "$GITHUB_WORKSPACE/docs/wiki" ]; then
|
|
cp -v "$GITHUB_WORKSPACE"/docs/wiki/*.md . 2>/dev/null || echo "No wiki files to copy"
|
|
fi
|
|
|
|
git add -A
|
|
if ! git diff --staged --quiet; then
|
|
git commit -m "docs: sync from docs/wiki/ at commit ${GITHUB_SHA:0:8}"
|
|
if git push origin master; then
|
|
echo "✓ Wiki successfully synced"
|
|
else
|
|
echo "⚠ Wiki push failed"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "No wiki changes to commit"
|
|
fi
|
|
|
|
build-linux-amd64:
|
|
needs: autotag
|
|
runs-on: ubuntu-latest
|
|
container:
|
|
image: ghcr.io/msicie/trcaa-linux-amd64:rust1.88-node22
|
|
credentials:
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 1
|
|
- name: Cache cargo registry
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: |
|
|
~/.cargo/registry/index
|
|
~/.cargo/registry/cache
|
|
~/.cargo/git/db
|
|
key: ${{ runner.os }}-cargo-linux-amd64-${{ hashFiles('**/Cargo.lock') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-cargo-linux-amd64-
|
|
- name: Cache npm
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ~/.npm
|
|
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-npm-
|
|
- name: Build
|
|
env:
|
|
APPIMAGE_EXTRACT_AND_RUN: "1"
|
|
run: |
|
|
npm ci --legacy-peer-deps
|
|
CI=true npx tauri build --target x86_64-unknown-linux-gnu
|
|
- name: Upload artifacts to GitHub release
|
|
env:
|
|
RELEASE_TAG: ${{ needs.autotag.outputs.release_tag }}
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
set -eu
|
|
TAG="${RELEASE_TAG}"
|
|
ARTIFACTS=$(find src-tauri/target/x86_64-unknown-linux-gnu/release/bundle -type f \
|
|
\( -name "*.deb" -o -name "*.rpm" \))
|
|
if [ -z "$ARTIFACTS" ]; then
|
|
echo "ERROR: No Linux amd64 artifacts found."
|
|
exit 1
|
|
fi
|
|
printf '%s\n' "$ARTIFACTS" | while IFS= read -r f; do
|
|
NAME="linux-amd64-$(basename "$f")"
|
|
echo "Uploading $NAME..."
|
|
gh release delete-asset "$TAG" "$NAME" --yes 2>/dev/null || true
|
|
gh release upload "$TAG" "$f#$NAME"
|
|
echo "✓ Uploaded $NAME"
|
|
done
|
|
|
|
build-windows-amd64:
|
|
needs: autotag
|
|
runs-on: ubuntu-latest
|
|
container:
|
|
image: ghcr.io/msicie/trcaa-windows-cross:rust1.88-node22
|
|
credentials:
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 1
|
|
- name: Cache cargo registry
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: |
|
|
~/.cargo/registry/index
|
|
~/.cargo/registry/cache
|
|
~/.cargo/git/db
|
|
key: ${{ runner.os }}-cargo-windows-${{ hashFiles('**/Cargo.lock') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-cargo-windows-
|
|
- name: Cache npm
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ~/.npm
|
|
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-npm-
|
|
- name: Build
|
|
env:
|
|
CC_x86_64_pc_windows_gnu: x86_64-w64-mingw32-gcc
|
|
CXX_x86_64_pc_windows_gnu: x86_64-w64-mingw32-g++
|
|
AR_x86_64_pc_windows_gnu: x86_64-w64-mingw32-ar
|
|
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER: x86_64-w64-mingw32-gcc
|
|
OPENSSL_NO_VENDOR: "0"
|
|
OPENSSL_STATIC: "1"
|
|
run: |
|
|
npm ci --legacy-peer-deps
|
|
CI=true npx tauri build --target x86_64-pc-windows-gnu
|
|
- name: Upload artifacts to GitHub release
|
|
env:
|
|
RELEASE_TAG: ${{ needs.autotag.outputs.release_tag }}
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
set -eu
|
|
TAG="${RELEASE_TAG}"
|
|
ARTIFACTS=$(find src-tauri/target/x86_64-pc-windows-gnu/release/bundle -type f \
|
|
\( -name "*.exe" -o -name "*.msi" \) 2>/dev/null)
|
|
if [ -z "$ARTIFACTS" ]; then
|
|
echo "ERROR: No Windows amd64 artifacts found."
|
|
exit 1
|
|
fi
|
|
printf '%s\n' "$ARTIFACTS" | while IFS= read -r f; do
|
|
NAME="windows-amd64-$(basename "$f")"
|
|
echo "Uploading $NAME..."
|
|
gh release delete-asset "$TAG" "$NAME" --yes 2>/dev/null || true
|
|
gh release upload "$TAG" "$f#$NAME"
|
|
echo "✓ Uploaded $NAME"
|
|
done
|
|
|
|
build-macos-arm64:
|
|
needs: autotag
|
|
runs-on: macos-latest
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 1
|
|
- name: Build
|
|
env:
|
|
MACOSX_DEPLOYMENT_TARGET: "11.0"
|
|
run: |
|
|
npm ci --legacy-peer-deps
|
|
rustup target add aarch64-apple-darwin
|
|
CI=true npx tauri build --target aarch64-apple-darwin --bundles app
|
|
APP=$(find src-tauri/target/aarch64-apple-darwin/release/bundle/macos -maxdepth 1 -type d -name "*.app" | head -n 1)
|
|
if [ -z "$APP" ]; then
|
|
echo "ERROR: Could not find macOS app bundle"
|
|
exit 1
|
|
fi
|
|
APP_NAME=$(basename "$APP" .app)
|
|
codesign --deep --force --sign - "$APP"
|
|
mkdir -p src-tauri/target/aarch64-apple-darwin/release/bundle/dmg
|
|
DMG=src-tauri/target/aarch64-apple-darwin/release/bundle/dmg/${APP_NAME}.dmg
|
|
hdiutil create -volname "$APP_NAME" -srcfolder "$APP" -ov -format UDZO "$DMG"
|
|
- name: Upload artifacts to GitHub release
|
|
env:
|
|
RELEASE_TAG: ${{ needs.autotag.outputs.release_tag }}
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
set -eu
|
|
TAG="${RELEASE_TAG}"
|
|
ARTIFACTS=$(find src-tauri/target/aarch64-apple-darwin/release/bundle -type f -name "*.dmg")
|
|
if [ -z "$ARTIFACTS" ]; then
|
|
echo "ERROR: No macOS arm64 DMG artifacts found."
|
|
exit 1
|
|
fi
|
|
printf '%s\n' "$ARTIFACTS" | while IFS= read -r f; do
|
|
NAME="macos-arm64-$(basename "$f")"
|
|
echo "Uploading $NAME..."
|
|
gh release delete-asset "$TAG" "$NAME" --yes 2>/dev/null || true
|
|
gh release upload "$TAG" "$f#$NAME"
|
|
echo "✓ Uploaded $NAME"
|
|
done
|
|
|
|
build-macos-intel:
|
|
needs: autotag
|
|
runs-on: macos-13
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 1
|
|
- name: Build
|
|
env:
|
|
MACOSX_DEPLOYMENT_TARGET: "10.15"
|
|
run: |
|
|
npm ci --legacy-peer-deps
|
|
rustup target add x86_64-apple-darwin
|
|
CI=true npx tauri build --target x86_64-apple-darwin --bundles app
|
|
APP=$(find src-tauri/target/x86_64-apple-darwin/release/bundle/macos -maxdepth 1 -type d -name "*.app" | head -n 1)
|
|
if [ -z "$APP" ]; then
|
|
echo "ERROR: Could not find macOS app bundle"
|
|
exit 1
|
|
fi
|
|
APP_NAME=$(basename "$APP" .app)
|
|
codesign --deep --force --sign - "$APP"
|
|
mkdir -p src-tauri/target/x86_64-apple-darwin/release/bundle/dmg
|
|
DMG=src-tauri/target/x86_64-apple-darwin/release/bundle/dmg/${APP_NAME}.dmg
|
|
hdiutil create -volname "$APP_NAME" -srcfolder "$APP" -ov -format UDZO "$DMG"
|
|
- name: Upload artifacts to GitHub release
|
|
env:
|
|
RELEASE_TAG: ${{ needs.autotag.outputs.release_tag }}
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
set -eu
|
|
TAG="${RELEASE_TAG}"
|
|
ARTIFACTS=$(find src-tauri/target/x86_64-apple-darwin/release/bundle -type f -name "*.dmg")
|
|
if [ -z "$ARTIFACTS" ]; then
|
|
echo "ERROR: No macOS Intel DMG artifacts found."
|
|
exit 1
|
|
fi
|
|
printf '%s\n' "$ARTIFACTS" | while IFS= read -r f; do
|
|
NAME="macos-intel-$(basename "$f")"
|
|
echo "Uploading $NAME..."
|
|
gh release delete-asset "$TAG" "$NAME" --yes 2>/dev/null || true
|
|
gh release upload "$TAG" "$f#$NAME"
|
|
echo "✓ Uploaded $NAME"
|
|
done
|
|
|
|
build-linux-arm64:
|
|
needs: autotag
|
|
runs-on: ubuntu-latest
|
|
container:
|
|
image: ghcr.io/msicie/trcaa-linux-arm64:rust1.88-node22
|
|
credentials:
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 1
|
|
- name: Cache cargo registry
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: |
|
|
~/.cargo/registry/index
|
|
~/.cargo/registry/cache
|
|
~/.cargo/git/db
|
|
key: ${{ runner.os }}-cargo-arm64-${{ hashFiles('**/Cargo.lock') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-cargo-arm64-
|
|
- name: Cache npm
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ~/.npm
|
|
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-npm-
|
|
- name: Build
|
|
env:
|
|
CC_aarch64_unknown_linux_gnu: aarch64-linux-gnu-gcc
|
|
CXX_aarch64_unknown_linux_gnu: aarch64-linux-gnu-g++
|
|
AR_aarch64_unknown_linux_gnu: aarch64-linux-gnu-ar
|
|
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
|
PKG_CONFIG_SYSROOT_DIR: /usr/aarch64-linux-gnu
|
|
PKG_CONFIG_PATH: /usr/lib/aarch64-linux-gnu/pkgconfig
|
|
PKG_CONFIG_ALLOW_CROSS: "1"
|
|
OPENSSL_NO_VENDOR: "0"
|
|
OPENSSL_STATIC: "1"
|
|
APPIMAGE_EXTRACT_AND_RUN: "1"
|
|
run: |
|
|
npm ci --legacy-peer-deps
|
|
CI=true npx tauri build --target aarch64-unknown-linux-gnu --bundles deb,rpm
|
|
- name: Upload artifacts to GitHub release
|
|
env:
|
|
RELEASE_TAG: ${{ needs.autotag.outputs.release_tag }}
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
set -eu
|
|
TAG="${RELEASE_TAG}"
|
|
ARTIFACTS=$(find src-tauri/target/aarch64-unknown-linux-gnu/release/bundle -type f \
|
|
\( -name "*.deb" -o -name "*.rpm" -o -name "*.AppImage" \))
|
|
if [ -z "$ARTIFACTS" ]; then
|
|
echo "ERROR: No Linux arm64 artifacts found."
|
|
exit 1
|
|
fi
|
|
printf '%s\n' "$ARTIFACTS" | while IFS= read -r f; do
|
|
NAME="linux-arm64-$(basename "$f")"
|
|
echo "Uploading $NAME..."
|
|
gh release delete-asset "$TAG" "$NAME" --yes 2>/dev/null || true
|
|
gh release upload "$TAG" "$f#$NAME"
|
|
echo "✓ Uploaded $NAME"
|
|
done
|