Some checks failed
PR Review Automation / review (pull_request) Successful in 3m57s
Test / rust-tests (pull_request) Has been cancelled
Test / frontend-typecheck (pull_request) Has been cancelled
Test / rust-fmt-check (pull_request) Has been cancelled
Test / rust-clippy (pull_request) Has been cancelled
Test / frontend-tests (pull_request) Has been cancelled
- Add release-beta.yml: triggers on push to beta, creates
v{CARGO}-beta.N pre-release tags with prerelease: true, builds all
four platforms; tag counter resets when Cargo.toml version bumps
- Add beta to test.yml push triggers so CI runs on direct pushes to
beta (pull_request already covers PRs targeting beta)
- Implement update_channel in AppSettings (state.rs) with serde
default "stable"; wire get/set_update_channel commands to AppState
instead of returning hardcoded stubs
- Implement channel-aware check_app_updates: queries /releases?limit=20
and picks first non-draft release matching the active channel
(stable = !prerelease, beta = prerelease), skipping drafts
- Document two-channel strategy in docs/wiki/CICD-Pipeline.md
Manual steps still required in Gitea UI:
1. Create beta branch from master
2. Apply same branch protection rules as master to beta
3. Set repo default PR target branch to beta
549 lines
23 KiB
YAML
549 lines
23 KiB
YAML
name: Release Beta
|
|
|
|
# Runs on every merge to beta — creates a v{CARGO_VERSION}-beta.N pre-release tag,
|
|
# builds all four platforms, and uploads artifacts. Wiki sync is intentionally
|
|
# omitted here; it only runs from master via auto-tag.yml.
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- beta
|
|
workflow_dispatch:
|
|
|
|
concurrency:
|
|
group: auto-tag-beta
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
autotag:
|
|
runs-on: linux-amd64
|
|
container:
|
|
image: alpine:latest
|
|
outputs:
|
|
release_tag: ${{ steps.bump.outputs.release_tag }}
|
|
steps:
|
|
- name: Create beta tag
|
|
id: bump
|
|
env:
|
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
|
run: |
|
|
set -eu
|
|
apk add --no-cache curl jq git
|
|
|
|
API="http://172.0.0.29:3000/api/v1/repos/$GITHUB_REPOSITORY"
|
|
|
|
git init
|
|
git remote add origin "http://oauth2:${RELEASE_TOKEN}@172.0.0.29:3000/${GITHUB_REPOSITORY}.git"
|
|
git fetch --depth=1 origin "$GITHUB_SHA"
|
|
git checkout FETCH_HEAD
|
|
git config user.name "gitea-actions[bot]"
|
|
git config user.email "gitea-actions@local"
|
|
|
|
CARGO_VERSION=$(grep '^version' src-tauri/Cargo.toml | head -1 | sed 's/version = "//;s/"//')
|
|
echo "Cargo.toml declares: $CARGO_VERSION"
|
|
|
|
# Find the highest existing beta.N for this Cargo version
|
|
LATEST_BETA=$(curl -s "$API/tags?limit=100" \
|
|
-H "Authorization: token $RELEASE_TOKEN" | \
|
|
jq -r '.[].name' | \
|
|
grep -E "^v${CARGO_VERSION}-beta\.[0-9]+$" | \
|
|
sort -t. -k4 -n | tail -1 || true)
|
|
echo "Latest beta tag: ${LATEST_BETA:-none}"
|
|
|
|
if [ -z "$LATEST_BETA" ]; then
|
|
NEXT="v${CARGO_VERSION}-beta.1"
|
|
else
|
|
N=$(echo "$LATEST_BETA" | sed "s/v${CARGO_VERSION}-beta\\.//")
|
|
NEXT="v${CARGO_VERSION}-beta.$((N + 1))"
|
|
fi
|
|
|
|
echo "Next beta tag: $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 "Pre-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: linux-amd64
|
|
container:
|
|
image: alpine:latest
|
|
steps:
|
|
- name: Install dependencies
|
|
run: apk add --no-cache git curl jq
|
|
|
|
- name: Checkout (full history + all tags)
|
|
env:
|
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
|
run: |
|
|
set -eu
|
|
git init
|
|
git remote add origin \
|
|
"http://oauth2:${RELEASE_TOKEN}@172.0.0.29:3000/${GITHUB_REPOSITORY}.git"
|
|
git fetch --unshallow origin || git fetch --depth=2147483647 origin || true
|
|
git fetch --tags origin
|
|
git checkout "$GITHUB_SHA" 2>/dev/null || git checkout FETCH_HEAD
|
|
git config user.name "gitea-actions[bot]"
|
|
git config user.email "gitea-actions@local"
|
|
|
|
- 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
|
|
|
|
# Include all tag types (stable + beta) for a proper diff range
|
|
PREV_TAG=$(git tag --sort=-version:refname | grep -v "^${CURRENT_TAG}$" | head -1 || echo "")
|
|
if [ -n "$PREV_TAG" ]; then
|
|
git-cliff --config cliff.toml "${PREV_TAG}..${CURRENT_TAG}" > /tmp/release_body.md || true
|
|
else
|
|
git log --pretty=format:"- %s" > /tmp/release_body.md || true
|
|
fi
|
|
echo "=== Release body preview ==="
|
|
cat /tmp/release_body.md
|
|
|
|
- name: Create or update Gitea pre-release
|
|
env:
|
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
|
RELEASE_TAG: ${{ needs.autotag.outputs.release_tag }}
|
|
run: |
|
|
set -eu
|
|
TAG="${RELEASE_TAG}"
|
|
API="http://172.0.0.29:3000/api/v1/repos/$GITHUB_REPOSITORY"
|
|
|
|
RELEASE_ID=$(curl -s "$API/releases/tags/$TAG" \
|
|
-H "Authorization: token $RELEASE_TOKEN" | jq -r '.id // empty')
|
|
|
|
if [ -z "$RELEASE_ID" ]; then
|
|
echo "Creating pre-release $TAG..."
|
|
RELEASE_ID=$(jq -n \
|
|
--arg tag "$TAG" \
|
|
--arg name "TFTSR $TAG" \
|
|
--rawfile body /tmp/release_body.md \
|
|
'{tag_name: $tag, name: $name, body: $body, draft: true, prerelease: true}' \
|
|
| curl -sf -X POST "$API/releases" \
|
|
-H "Authorization: token $RELEASE_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
--data @- \
|
|
| jq -r '.id')
|
|
echo "✓ Pre-release created (id=$RELEASE_ID)"
|
|
else
|
|
echo "Updating existing release $TAG (id=$RELEASE_ID)..."
|
|
jq -n --rawfile body /tmp/release_body.md '{body: $body}' \
|
|
| curl -sf -X PATCH "$API/releases/$RELEASE_ID" \
|
|
-H "Authorization: token $RELEASE_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
--data @-
|
|
echo "✓ Release body updated"
|
|
fi
|
|
|
|
if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then
|
|
echo "ERROR: Failed to create or locate release for $TAG"
|
|
exit 1
|
|
fi
|
|
|
|
- name: Upload CHANGELOG.md as release asset
|
|
env:
|
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
|
RELEASE_TAG: ${{ needs.autotag.outputs.release_tag }}
|
|
run: |
|
|
set -eu
|
|
TAG="${RELEASE_TAG}"
|
|
API="http://172.0.0.29:3000/api/v1/repos/$GITHUB_REPOSITORY"
|
|
RELEASE_ID=$(curl -sf "$API/releases/tags/$TAG" \
|
|
-H "Authorization: token $RELEASE_TOKEN" | jq -r '.id')
|
|
if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then
|
|
echo "ERROR: Could not find release for tag $TAG"
|
|
exit 1
|
|
fi
|
|
# Generate a minimal changelog file for the asset
|
|
git log --pretty=format:"- %s" -20 > CHANGELOG.md || true
|
|
EXISTING_ID=$(curl -sf "$API/releases/$RELEASE_ID" \
|
|
-H "Authorization: token $RELEASE_TOKEN" \
|
|
| jq -r '.assets[]? | select(.name == "CHANGELOG.md") | .id')
|
|
if [ -n "$EXISTING_ID" ]; then
|
|
curl -sf -X DELETE "$API/releases/$RELEASE_ID/assets/$EXISTING_ID" \
|
|
-H "Authorization: token $RELEASE_TOKEN"
|
|
fi
|
|
curl -sf -X POST "$API/releases/$RELEASE_ID/assets" \
|
|
-H "Authorization: token $RELEASE_TOKEN" \
|
|
-F "attachment=@CHANGELOG.md;filename=CHANGELOG.md"
|
|
echo "✓ CHANGELOG.md uploaded"
|
|
|
|
build-linux-amd64:
|
|
needs: autotag
|
|
runs-on: linux-amd64
|
|
container:
|
|
image: 172.0.0.29:3000/sarman/tftsr-linux-amd64:rust1.88-node22
|
|
steps:
|
|
- name: Checkout
|
|
run: |
|
|
git init
|
|
git remote add origin http://172.0.0.29:3000/sarman/tftsr-devops_investigation.git
|
|
git fetch --depth=1 origin "$GITHUB_SHA"
|
|
git checkout FETCH_HEAD
|
|
- 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
|
|
env:
|
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
|
RELEASE_TAG: ${{ needs.autotag.outputs.release_tag }}
|
|
run: |
|
|
set -eu
|
|
API="http://172.0.0.29:3000/api/v1/repos/$GITHUB_REPOSITORY"
|
|
TAG="${RELEASE_TAG}"
|
|
echo "Uploading artifacts for $TAG..."
|
|
curl -sf -X POST "$API/releases" \
|
|
-H "Authorization: token $RELEASE_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{\"tag_name\":\"$TAG\",\"name\":\"TFTSR $TAG\",\"body\":\"Pre-release $TAG\",\"draft\":false,\"prerelease\":true}" || true
|
|
RELEASE_ID=$(curl -sf "$API/releases/tags/$TAG" \
|
|
-H "Authorization: token $RELEASE_TOKEN" | jq -r '.id')
|
|
if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then
|
|
echo "ERROR: Failed to get release ID for $TAG"
|
|
exit 1
|
|
fi
|
|
echo "Release ID: $RELEASE_ID"
|
|
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 were found to upload."
|
|
exit 1
|
|
fi
|
|
printf '%s\n' "$ARTIFACTS" | while IFS= read -r f; do
|
|
NAME=$(basename "$f")
|
|
UPLOAD_NAME="linux-amd64-$NAME"
|
|
echo "Uploading $UPLOAD_NAME..."
|
|
EXISTING_IDS=$(curl -sf "$API/releases/$RELEASE_ID" \
|
|
-H "Authorization: token $RELEASE_TOKEN" \
|
|
| jq -r --arg name "$UPLOAD_NAME" '.assets[]? | select(.name == $name) | .id')
|
|
if [ -n "$EXISTING_IDS" ]; then
|
|
printf '%s\n' "$EXISTING_IDS" | while IFS= read -r id; do
|
|
[ -n "$id" ] || continue
|
|
curl -sf -X DELETE "$API/releases/$RELEASE_ID/assets/$id" \
|
|
-H "Authorization: token $RELEASE_TOKEN"
|
|
done
|
|
fi
|
|
RESP_FILE=$(mktemp)
|
|
HTTP_CODE=$(curl -sS -o "$RESP_FILE" -w "%{http_code}" -X POST "$API/releases/$RELEASE_ID/assets" \
|
|
-H "Authorization: token $RELEASE_TOKEN" \
|
|
-F "attachment=@$f;filename=$UPLOAD_NAME")
|
|
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
|
|
echo "✓ Uploaded $UPLOAD_NAME"
|
|
else
|
|
echo "✗ Upload failed for $UPLOAD_NAME (HTTP $HTTP_CODE)"
|
|
python -c 'import pathlib,sys;print(pathlib.Path(sys.argv[1]).read_text(errors="replace")[:2000])' "$RESP_FILE"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
build-windows-amd64:
|
|
needs: autotag
|
|
runs-on: linux-amd64
|
|
container:
|
|
image: 172.0.0.29:3000/sarman/tftsr-windows-cross:rust1.88-node22
|
|
steps:
|
|
- name: Checkout
|
|
run: |
|
|
git init
|
|
git remote add origin http://172.0.0.29:3000/sarman/tftsr-devops_investigation.git
|
|
git fetch --depth=1 origin "$GITHUB_SHA"
|
|
git checkout FETCH_HEAD
|
|
- 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
|
|
env:
|
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
|
RELEASE_TAG: ${{ needs.autotag.outputs.release_tag }}
|
|
run: |
|
|
set -eu
|
|
API="http://172.0.0.29:3000/api/v1/repos/$GITHUB_REPOSITORY"
|
|
TAG="${RELEASE_TAG}"
|
|
echo "Uploading artifacts for $TAG..."
|
|
curl -sf -X POST "$API/releases" \
|
|
-H "Authorization: token $RELEASE_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{\"tag_name\":\"$TAG\",\"name\":\"TFTSR $TAG\",\"body\":\"Pre-release $TAG\",\"draft\":false,\"prerelease\":true}" || true
|
|
RELEASE_ID=$(curl -sf "$API/releases/tags/$TAG" \
|
|
-H "Authorization: token $RELEASE_TOKEN" | jq -r '.id')
|
|
if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then
|
|
echo "ERROR: Failed to get release ID for $TAG"
|
|
exit 1
|
|
fi
|
|
echo "Release ID: $RELEASE_ID"
|
|
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 were found to upload."
|
|
exit 1
|
|
fi
|
|
printf '%s\n' "$ARTIFACTS" | while IFS= read -r f; do
|
|
NAME=$(basename "$f")
|
|
echo "Uploading $NAME..."
|
|
EXISTING_IDS=$(curl -sf "$API/releases/$RELEASE_ID" \
|
|
-H "Authorization: token $RELEASE_TOKEN" \
|
|
| jq -r --arg name "$NAME" '.assets[]? | select(.name == $name) | .id')
|
|
if [ -n "$EXISTING_IDS" ]; then
|
|
printf '%s\n' "$EXISTING_IDS" | while IFS= read -r id; do
|
|
[ -n "$id" ] || continue
|
|
curl -sf -X DELETE "$API/releases/$RELEASE_ID/assets/$id" \
|
|
-H "Authorization: token $RELEASE_TOKEN"
|
|
done
|
|
fi
|
|
RESP_FILE=$(mktemp)
|
|
HTTP_CODE=$(curl -sS -o "$RESP_FILE" -w "%{http_code}" -X POST "$API/releases/$RELEASE_ID/assets" \
|
|
-H "Authorization: token $RELEASE_TOKEN" \
|
|
-F "attachment=@$f;filename=$NAME")
|
|
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
|
|
echo "✓ Uploaded $NAME"
|
|
else
|
|
echo "✗ Upload failed for $NAME (HTTP $HTTP_CODE)"
|
|
python -c 'import pathlib,sys;print(pathlib.Path(sys.argv[1]).read_text(errors="replace")[:2000])' "$RESP_FILE"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
build-macos-arm64:
|
|
needs: autotag
|
|
runs-on: macos-arm64
|
|
steps:
|
|
- name: Checkout
|
|
run: |
|
|
git init
|
|
git remote add origin http://172.0.0.29:3000/sarman/tftsr-devops_investigation.git
|
|
git fetch --depth=1 origin "$GITHUB_SHA"
|
|
git checkout FETCH_HEAD
|
|
- 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
|
|
env:
|
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
|
RELEASE_TAG: ${{ needs.autotag.outputs.release_tag }}
|
|
run: |
|
|
set -eu
|
|
API="http://172.0.0.29:3000/api/v1/repos/$GITHUB_REPOSITORY"
|
|
TAG="${RELEASE_TAG}"
|
|
echo "Uploading artifacts for $TAG..."
|
|
curl -sf -X POST "$API/releases" \
|
|
-H "Authorization: token $RELEASE_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{\"tag_name\":\"$TAG\",\"name\":\"TFTSR $TAG\",\"body\":\"Pre-release $TAG\",\"draft\":false,\"prerelease\":true}" || true
|
|
RELEASE_ID=$(curl -sf "$API/releases/tags/$TAG" \
|
|
-H "Authorization: token $RELEASE_TOKEN" | jq -r '.id')
|
|
if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then
|
|
echo "ERROR: Failed to get release ID for $TAG"
|
|
exit 1
|
|
fi
|
|
echo "Release ID: $RELEASE_ID"
|
|
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 were found to upload."
|
|
exit 1
|
|
fi
|
|
printf '%s\n' "$ARTIFACTS" | while IFS= read -r f; do
|
|
NAME=$(basename "$f")
|
|
echo "Uploading $NAME..."
|
|
EXISTING_IDS=$(curl -sf "$API/releases/$RELEASE_ID" \
|
|
-H "Authorization: token $RELEASE_TOKEN" \
|
|
| jq -r --arg name "$NAME" '.assets[]? | select(.name == $name) | .id')
|
|
if [ -n "$EXISTING_IDS" ]; then
|
|
printf '%s\n' "$EXISTING_IDS" | while IFS= read -r id; do
|
|
[ -n "$id" ] || continue
|
|
curl -sf -X DELETE "$API/releases/$RELEASE_ID/assets/$id" \
|
|
-H "Authorization: token $RELEASE_TOKEN"
|
|
done
|
|
fi
|
|
RESP_FILE=$(mktemp)
|
|
HTTP_CODE=$(curl -sS -o "$RESP_FILE" -w "%{http_code}" -X POST "$API/releases/$RELEASE_ID/assets" \
|
|
-H "Authorization: token $RELEASE_TOKEN" \
|
|
-F "attachment=@$f;filename=$NAME")
|
|
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
|
|
echo "✓ Uploaded $NAME"
|
|
else
|
|
echo "✗ Upload failed for $NAME (HTTP $HTTP_CODE)"
|
|
python -c 'import pathlib,sys;print(pathlib.Path(sys.argv[1]).read_text(errors="replace")[:2000])' "$RESP_FILE"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
build-linux-arm64:
|
|
needs: autotag
|
|
runs-on: linux-amd64
|
|
container:
|
|
image: 172.0.0.29:3000/sarman/tftsr-linux-arm64:rust1.88-node22
|
|
steps:
|
|
- name: Checkout
|
|
run: |
|
|
git init
|
|
git remote add origin http://172.0.0.29:3000/sarman/tftsr-devops_investigation.git
|
|
git fetch --depth=1 origin "$GITHUB_SHA"
|
|
git checkout FETCH_HEAD
|
|
- 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
|
|
env:
|
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
|
RELEASE_TAG: ${{ needs.autotag.outputs.release_tag }}
|
|
run: |
|
|
set -eu
|
|
API="http://172.0.0.29:3000/api/v1/repos/$GITHUB_REPOSITORY"
|
|
TAG="${RELEASE_TAG}"
|
|
echo "Uploading artifacts for $TAG..."
|
|
curl -sf -X POST "$API/releases" \
|
|
-H "Authorization: token $RELEASE_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{\"tag_name\":\"$TAG\",\"name\":\"TFTSR $TAG\",\"body\":\"Pre-release $TAG\",\"draft\":false,\"prerelease\":true}" || true
|
|
RELEASE_ID=$(curl -sf "$API/releases/tags/$TAG" \
|
|
-H "Authorization: token $RELEASE_TOKEN" | jq -r '.id')
|
|
if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then
|
|
echo "ERROR: Failed to get release ID for $TAG"
|
|
exit 1
|
|
fi
|
|
echo "Release ID: $RELEASE_ID"
|
|
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 were found to upload."
|
|
exit 1
|
|
fi
|
|
printf '%s\n' "$ARTIFACTS" | while IFS= read -r f; do
|
|
NAME=$(basename "$f")
|
|
UPLOAD_NAME="linux-arm64-$NAME"
|
|
echo "Uploading $UPLOAD_NAME..."
|
|
EXISTING_IDS=$(curl -sf "$API/releases/$RELEASE_ID" \
|
|
-H "Authorization: token $RELEASE_TOKEN" \
|
|
| jq -r --arg name "$UPLOAD_NAME" '.assets[]? | select(.name == $name) | .id')
|
|
if [ -n "$EXISTING_IDS" ]; then
|
|
printf '%s\n' "$EXISTING_IDS" | while IFS= read -r id; do
|
|
[ -n "$id" ] || continue
|
|
curl -sf -X DELETE "$API/releases/$RELEASE_ID/assets/$id" \
|
|
-H "Authorization: token $RELEASE_TOKEN"
|
|
done
|
|
fi
|
|
RESP_FILE=$(mktemp)
|
|
HTTP_CODE=$(curl -sS -o "$RESP_FILE" -w "%{http_code}" -X POST "$API/releases/$RELEASE_ID/assets" \
|
|
-H "Authorization: token $RELEASE_TOKEN" \
|
|
-F "attachment=@$f;filename=$UPLOAD_NAME")
|
|
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
|
|
echo "✓ Uploaded $UPLOAD_NAME"
|
|
else
|
|
echo "✗ Upload failed for $UPLOAD_NAME (HTTP $HTTP_CODE)"
|
|
python -c 'import pathlib,sys;print(pathlib.Path(sys.argv[1]).read_text(errors="replace")[:2000])' "$RESP_FILE"
|
|
exit 1
|
|
fi
|
|
done
|