ci: add release backfill and dmg diagnostics (#1570)
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
label="${1:-failure}"
|
||||
platform="${DESKTOP_DIAGNOSTICS_PLATFORM:?DESKTOP_DIAGNOSTICS_PLATFORM is required}"
|
||||
rust_target="${DESKTOP_DIAGNOSTICS_RUST_TARGET:?DESKTOP_DIAGNOSTICS_RUST_TARGET is required}"
|
||||
diag_dir="$GITHUB_WORKSPACE/dist/desktop-diagnostics"
|
||||
bundle_root="$GITHUB_WORKSPACE/apps/desktop/src-tauri/target/${rust_target}/release/bundle"
|
||||
|
||||
mkdir -p "$diag_dir"
|
||||
if [ ! -d "$bundle_root" ]; then
|
||||
bundle_root="$GITHUB_WORKSPACE/apps/desktop/src-tauri/target/release/bundle"
|
||||
fi
|
||||
|
||||
{
|
||||
echo "label=$label"
|
||||
echo "platform=$platform"
|
||||
echo "rust_target=$rust_target"
|
||||
echo "date=$(date -u '+%Y-%m-%dT%H:%M:%SZ')"
|
||||
echo
|
||||
echo "## system"
|
||||
uname -a || true
|
||||
sw_vers || true
|
||||
echo
|
||||
echo "## disk"
|
||||
df -h || true
|
||||
echo
|
||||
echo "## hdiutil info"
|
||||
hdiutil info || true
|
||||
echo
|
||||
echo "## mounts"
|
||||
mount || true
|
||||
echo
|
||||
echo "## related processes"
|
||||
ps aux | grep -E 'hdiutil|diskimages|bundle_dmg|pnpm|cargo' | grep -v grep || true
|
||||
echo
|
||||
echo "## bundle files"
|
||||
if [ -d "$bundle_root" ]; then
|
||||
find "$bundle_root" -maxdepth 5 -print || true
|
||||
else
|
||||
echo "Missing bundle root: $bundle_root"
|
||||
fi
|
||||
} > "$diag_dir/macos-${platform}-${label}.txt"
|
||||
|
||||
if [ -f "$bundle_root/dmg/bundle_dmg.sh" ]; then
|
||||
cp "$bundle_root/dmg/bundle_dmg.sh" "$diag_dir/bundle_dmg-${platform}-${label}.sh" || true
|
||||
fi
|
||||
@@ -0,0 +1,117 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Contract tests for the maintainer release workflow."""
|
||||
|
||||
import re
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||
WORKFLOW_PATH = REPO_ROOT / ".github" / "workflows" / "release.yml"
|
||||
DIAGNOSTICS_PATH = REPO_ROOT / ".github" / "scripts" / "collect-macos-desktop-diagnostics.sh"
|
||||
WORKFLOW = WORKFLOW_PATH.read_text()
|
||||
DIAGNOSTICS = DIAGNOSTICS_PATH.read_text()
|
||||
|
||||
|
||||
def step_block(name: str) -> str:
|
||||
marker = f" - name: {name}"
|
||||
start = WORKFLOW.find(marker)
|
||||
if start == -1:
|
||||
raise AssertionError(f"step not found: {name}")
|
||||
next_step = re.search(r"\n - (?:name|uses): ", WORKFLOW[start + 1 :])
|
||||
end = len(WORKFLOW) if next_step is None else start + 1 + next_step.start()
|
||||
return WORKFLOW[start:end]
|
||||
|
||||
|
||||
def job_block(name: str) -> str:
|
||||
marker = f" {name}:"
|
||||
start = WORKFLOW.find(marker)
|
||||
if start == -1:
|
||||
raise AssertionError(f"job not found: {name}")
|
||||
next_job = re.search(r"\n [a-zA-Z0-9_-]+:\n", WORKFLOW[start + 1 :])
|
||||
end = len(WORKFLOW) if next_job is None else start + 1 + next_job.start()
|
||||
return WORKFLOW[start:end]
|
||||
|
||||
|
||||
class ReleaseWorkflowContractTest(unittest.TestCase):
|
||||
def test_backfill_tag_input_uses_existing_tag_without_recreating_it(self) -> None:
|
||||
self.assertIn("backfill_tag:", WORKFLOW)
|
||||
self.assertIn("BACKFILL_TAG: ${{ inputs.backfill_tag }}", WORKFLOW)
|
||||
self.assertIn("Backfill existing release tag:", step_block("Compute next version"))
|
||||
self.assertIn("backfill_tag is set; the 'bump' input", WORKFLOW)
|
||||
self.assertIn("backfill_tag cannot be used: no existing release tags found.", WORKFLOW)
|
||||
self.assertIn("must be the latest release tag", WORKFLOW)
|
||||
self.assertIn("(expected ${next})", WORKFLOW)
|
||||
self.assertIn('BACKFILL_REF="refs/tags/$BACKFILL_TAG"', WORKFLOW)
|
||||
self.assertIn('echo "ref=$BACKFILL_REF" >> "$GITHUB_OUTPUT"', WORKFLOW)
|
||||
self.assertIn('echo "ref=refs/tags/$TAG" >> "$GITHUB_OUTPUT"', WORKFLOW)
|
||||
self.assertNotIn("ref: ${{ needs.prepare.outputs.tag }}", WORKFLOW)
|
||||
|
||||
for path in (
|
||||
"apps/cli/package.json",
|
||||
"apps/desktop/package.json",
|
||||
"apps/desktop/src-tauri/tauri.conf.json",
|
||||
"apps/desktop/src-tauri/Cargo.toml",
|
||||
"apps/desktop/src-tauri/Cargo.lock",
|
||||
):
|
||||
self.assertIn(path, WORKFLOW)
|
||||
|
||||
for name in (
|
||||
"Bump version + generate CHANGELOG (in working tree)",
|
||||
"Create release PR + squash-merge + tag",
|
||||
):
|
||||
self.assertIn("inputs.backfill_tag == ''", step_block(name))
|
||||
|
||||
def test_backfill_tag_still_runs_build_and_publish_jobs(self) -> None:
|
||||
for name in (
|
||||
"build-web",
|
||||
"build-bundles",
|
||||
"build-desktop",
|
||||
"docker-amd64",
|
||||
"docker-arm64",
|
||||
"docker-manifest",
|
||||
"docker-universal-amd64",
|
||||
"docker-universal-arm64",
|
||||
"docker-universal-manifest",
|
||||
"publish-release",
|
||||
"publish-npm",
|
||||
"update-homebrew-tap",
|
||||
):
|
||||
block = job_block(name)
|
||||
self.assertIn("if: ${{ !inputs.dry_run", block)
|
||||
self.assertNotIn("inputs.backfill_tag == ''", block)
|
||||
|
||||
def test_macos_dmg_build_has_retry_timeout_and_diagnostics(self) -> None:
|
||||
build = step_block("Build Tauri desktop app")
|
||||
self.assertIn("timeout-minutes: 70", build)
|
||||
self.assertIn("TAURI_BUNDLE_ATTEMPTS:", build)
|
||||
self.assertIn("run_with_timeout", build)
|
||||
self.assertIn("collect_macos_desktop_diagnostics", build)
|
||||
self.assertIn("DESKTOP_DIAGNOSTICS_SCRIPT", build)
|
||||
self.assertIn("terminate_process_tree_with_signal", build)
|
||||
self.assertIn("else\n status=$?", build)
|
||||
self.assertIn("for attempt in", build)
|
||||
|
||||
helper = step_block("Prepare macOS desktop diagnostics helper")
|
||||
self.assertIn("continue-on-error: true", helper)
|
||||
self.assertIn("github.workflow_sha", helper)
|
||||
self.assertIn("DESKTOP_DIAGNOSTICS_SCRIPT=$helper", helper)
|
||||
|
||||
collect = step_block("Collect macOS desktop diagnostics")
|
||||
self.assertIn("if: failure() && startsWith(matrix.platform, 'macos-')", collect)
|
||||
self.assertIn("DESKTOP_DIAGNOSTICS_SCRIPT", collect)
|
||||
|
||||
upload = step_block("Upload macOS desktop diagnostics")
|
||||
self.assertIn("if: failure() && startsWith(matrix.platform, 'macos-')", upload)
|
||||
self.assertIn("dist/desktop-diagnostics/**", upload)
|
||||
self.assertIn("/release/bundle/dmg/**", upload)
|
||||
|
||||
self.assertIn("hdiutil info", DIAGNOSTICS)
|
||||
self.assertIn("df -h", DIAGNOSTICS)
|
||||
self.assertIn("bundle_dmg.sh", DIAGNOSTICS)
|
||||
self.assertIn('cp "$bundle_root/dmg/bundle_dmg.sh"', DIAGNOSTICS)
|
||||
self.assertIn("|| true", DIAGNOSTICS)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -7,12 +7,16 @@ on:
|
||||
- ".github/workflows/**"
|
||||
- ".github/scripts/lint-action-pinning.py"
|
||||
- ".github/scripts/lint-action-pinning_test.py"
|
||||
- ".github/scripts/collect-macos-desktop-diagnostics.sh"
|
||||
- ".github/scripts/release-workflow-contract_test.py"
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
- ".github/workflows/**"
|
||||
- ".github/scripts/lint-action-pinning.py"
|
||||
- ".github/scripts/lint-action-pinning_test.py"
|
||||
- ".github/scripts/collect-macos-desktop-diagnostics.sh"
|
||||
- ".github/scripts/release-workflow-contract_test.py"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -36,5 +40,8 @@ jobs:
|
||||
- name: Test action-pinning lint
|
||||
run: python3 .github/scripts/lint-action-pinning_test.py
|
||||
|
||||
- name: Test release workflow contract
|
||||
run: python3 .github/scripts/release-workflow-contract_test.py
|
||||
|
||||
- name: Verify action refs
|
||||
run: python3 .github/scripts/lint-action-pinning.py
|
||||
|
||||
+245
-14
@@ -52,6 +52,11 @@ on:
|
||||
description: "Build desktop artifacts only (no PR, tag, publish, npm, or tap update)"
|
||||
type: boolean
|
||||
default: false
|
||||
backfill_tag:
|
||||
description: "Existing release tag to rebuild/publish (for recovery; leave empty for normal release)"
|
||||
required: false
|
||||
default: ""
|
||||
type: string
|
||||
|
||||
# Default to read-only at the workflow level. Each job opts into the writes
|
||||
# it actually needs.
|
||||
@@ -109,11 +114,104 @@ jobs:
|
||||
- name: Compute next version
|
||||
id: compute
|
||||
env:
|
||||
BACKFILL_TAG: ${{ inputs.backfill_tag }}
|
||||
BUMP: ${{ inputs.bump }}
|
||||
DRY_RUN: ${{ inputs.dry_run }}
|
||||
DESKTOP_VALIDATION_ONLY: ${{ inputs.desktop_validation_only }}
|
||||
CURRENT_REF: ${{ github.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ -n "$BACKFILL_TAG" ]; then
|
||||
echo "::notice::backfill_tag is set; the 'bump' input ($BUMP) is ignored."
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo "backfill_tag cannot be combined with dry_run." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$DESKTOP_VALIDATION_ONLY" = "true" ]; then
|
||||
echo "backfill_tag cannot be combined with desktop_validation_only." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$BACKFILL_TAG" in
|
||||
refs/tags/*) BACKFILL_TAG="${BACKFILL_TAG#refs/tags/}" ;;
|
||||
esac
|
||||
|
||||
if [[ ! "$BACKFILL_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "backfill_tag must be a SemVer release tag like v1.2.3." >&2
|
||||
exit 1
|
||||
fi
|
||||
BACKFILL_REF="refs/tags/$BACKFILL_TAG"
|
||||
if ! git rev-parse --verify --quiet "${BACKFILL_REF}^{commit}" >/dev/null; then
|
||||
echo "backfill_tag does not exist: $BACKFILL_TAG" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NEXT="${BACKFILL_TAG#v}"
|
||||
LATEST_RELEASE_TAG="$(git tag --list 'v*' | python3 -c "
|
||||
import sys, re
|
||||
best = None
|
||||
best_tag = ''
|
||||
for t in (l.strip() for l in sys.stdin if l.strip()):
|
||||
s = t.lstrip('v')
|
||||
m3 = re.match(r'^(\d+)\.(\d+)\.(\d+)$', s)
|
||||
m2 = re.match(r'^(\d+)\.(\d+)$', s)
|
||||
if m3:
|
||||
v = tuple(int(x) for x in m3.groups())
|
||||
tag = f'v{v[0]}.{v[1]}.{v[2]}'
|
||||
elif m2:
|
||||
v = (int(m2.group(1)), int(m2.group(2)), 0)
|
||||
tag = f'v{v[0]}.{v[1]}.{v[2]}'
|
||||
else:
|
||||
continue
|
||||
if best is None or v > best:
|
||||
best = v
|
||||
best_tag = tag
|
||||
print(best_tag)
|
||||
")"
|
||||
if [ -z "$LATEST_RELEASE_TAG" ]; then
|
||||
echo "backfill_tag cannot be used: no existing release tags found." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$LATEST_RELEASE_TAG" != "$BACKFILL_TAG" ]; then
|
||||
echo "backfill_tag must be the latest release tag ($LATEST_RELEASE_TAG) because backfill publishes mutable channels." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BACKFILL_REF="$BACKFILL_REF" BACKFILL_TAG="$BACKFILL_TAG" NEXT="$NEXT" node <<'NODE'
|
||||
const { execFileSync } = require("node:child_process");
|
||||
|
||||
const tag = process.env.BACKFILL_TAG;
|
||||
const ref = process.env.BACKFILL_REF;
|
||||
const next = process.env.NEXT;
|
||||
const show = (path) => execFileSync("git", ["show", `${ref}:${path}`], { encoding: "utf8" });
|
||||
const versions = new Map([
|
||||
["apps/cli/package.json", JSON.parse(show("apps/cli/package.json")).version],
|
||||
["apps/desktop/package.json", JSON.parse(show("apps/desktop/package.json")).version],
|
||||
["apps/desktop/src-tauri/tauri.conf.json", JSON.parse(show("apps/desktop/src-tauri/tauri.conf.json")).version],
|
||||
["apps/desktop/src-tauri/Cargo.toml", show("apps/desktop/src-tauri/Cargo.toml").match(/^version = "([^"]+)"/m)?.[1]],
|
||||
[
|
||||
"apps/desktop/src-tauri/Cargo.lock",
|
||||
show("apps/desktop/src-tauri/Cargo.lock").match(/\[\[package\]\]\nname = "kandev-desktop"\nversion = "([^"]+)"/)?.[1],
|
||||
],
|
||||
]);
|
||||
|
||||
for (const [path, version] of versions) {
|
||||
if (version !== next) {
|
||||
console.error(`backfill_tag version mismatch: ${tag} points to ${path} version ${version ?? "<missing>"} (expected ${next}).`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
NODE
|
||||
|
||||
TAG="$BACKFILL_TAG"
|
||||
echo "Backfill existing release tag: $TAG"
|
||||
echo "Next version: $NEXT"
|
||||
echo "version=$NEXT" >> "$GITHUB_OUTPUT"
|
||||
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
||||
echo "ref=$BACKFILL_REF" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
PKG_VERSION="$(node -p "require('./apps/cli/package.json').version")"
|
||||
|
||||
# Find latest git tag, normalizing legacy two-part tags (vM.m → M.m.0)
|
||||
@@ -164,7 +262,7 @@ jobs:
|
||||
if [ "$DESKTOP_VALIDATION_ONLY" = "true" ]; then
|
||||
echo "ref=$CURRENT_REF" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "ref=$TAG" >> "$GITHUB_OUTPUT"
|
||||
echo "ref=refs/tags/$TAG" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
# Sanity: tag must not already exist
|
||||
@@ -178,7 +276,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Bump version + generate CHANGELOG (in working tree)
|
||||
if: ${{ !inputs.dry_run && !inputs.desktop_validation_only }}
|
||||
if: ${{ !inputs.dry_run && !inputs.desktop_validation_only && inputs.backfill_tag == '' }}
|
||||
env:
|
||||
NEXT: ${{ steps.compute.outputs.version }}
|
||||
TAG: ${{ steps.compute.outputs.tag }}
|
||||
@@ -216,7 +314,7 @@ jobs:
|
||||
git-cliff --tag "$TAG" -o CHANGELOG.md
|
||||
|
||||
- name: Create release PR + squash-merge + tag
|
||||
if: ${{ !inputs.dry_run && !inputs.desktop_validation_only }}
|
||||
if: ${{ !inputs.dry_run && !inputs.desktop_validation_only && inputs.backfill_tag == '' }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NEXT: ${{ steps.compute.outputs.version }}
|
||||
@@ -482,6 +580,34 @@ jobs:
|
||||
ref: ${{ needs.prepare.outputs.ref }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Prepare macOS desktop diagnostics helper
|
||||
if: startsWith(matrix.platform, 'macos-')
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
helper="$RUNNER_TEMP/collect-macos-desktop-diagnostics.sh"
|
||||
mkdir -p "$(dirname "$helper")"
|
||||
if [ -f "$GITHUB_WORKSPACE/.github/scripts/collect-macos-desktop-diagnostics.sh" ]; then
|
||||
cp "$GITHUB_WORKSPACE/.github/scripts/collect-macos-desktop-diagnostics.sh" "$helper"
|
||||
else
|
||||
encoded_helper="$RUNNER_TEMP/collect-macos-desktop-diagnostics.sh.b64"
|
||||
gh api \
|
||||
"repos/${{ github.repository }}/contents/.github/scripts/collect-macos-desktop-diagnostics.sh?ref=${{ github.workflow_sha }}" \
|
||||
--jq .content > "$encoded_helper"
|
||||
HELPER="$helper" ENCODED_HELPER="$encoded_helper" python3 - <<'PY'
|
||||
import base64
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
encoded = Path(os.environ["ENCODED_HELPER"]).read_text()
|
||||
Path(os.environ["HELPER"]).write_bytes(base64.b64decode(encoded))
|
||||
PY
|
||||
fi
|
||||
chmod +x "$helper"
|
||||
echo "DESKTOP_DIAGNOSTICS_SCRIPT=$helper" >> "$GITHUB_ENV"
|
||||
|
||||
- uses: pnpm/action-setup@a8198c4bff370c8506180b035930dea56dbd5288 # v5
|
||||
with:
|
||||
version: "9.15.9"
|
||||
@@ -640,8 +766,13 @@ jobs:
|
||||
}
|
||||
|
||||
- name: Build Tauri desktop app
|
||||
timeout-minutes: 70
|
||||
env:
|
||||
CI: "true"
|
||||
DESKTOP_DIAGNOSTICS_PLATFORM: ${{ matrix.platform }}
|
||||
DESKTOP_DIAGNOSTICS_RUST_TARGET: ${{ matrix.rust_target }}
|
||||
TAURI_BUNDLE_ATTEMPTS: ${{ startsWith(matrix.platform, 'macos-') && '2' || '1' }}
|
||||
TAURI_BUILD_TIMEOUT_SECONDS: ${{ startsWith(matrix.platform, 'macos-') && '1800' || '0' }}
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
@@ -676,10 +807,110 @@ jobs:
|
||||
fi
|
||||
pnpm -C apps --filter @kandev/desktop build:vite
|
||||
cd apps/desktop
|
||||
pnpm tauri build \
|
||||
--features desktop-runtime \
|
||||
--target "${{ matrix.rust_target }}" \
|
||||
--bundles "${{ matrix.tauri_bundles }}"
|
||||
|
||||
collect_macos_desktop_diagnostics() {
|
||||
local label="${1:-failure}"
|
||||
if [[ "${{ matrix.platform }}" != macos-* ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
bash "${DESKTOP_DIAGNOSTICS_SCRIPT:-$GITHUB_WORKSPACE/.github/scripts/collect-macos-desktop-diagnostics.sh}" "$label" || true
|
||||
}
|
||||
|
||||
terminate_process_tree() {
|
||||
local pid="$1"
|
||||
terminate_process_tree_with_signal "$pid" TERM
|
||||
sleep 5
|
||||
terminate_process_tree_with_signal "$pid" KILL
|
||||
}
|
||||
|
||||
terminate_process_tree_with_signal() {
|
||||
local pid="$1"
|
||||
local signal="$2"
|
||||
local child
|
||||
while IFS= read -r child; do
|
||||
[ -n "$child" ] || continue
|
||||
terminate_process_tree_with_signal "$child" "$signal"
|
||||
done < <(pgrep -P "$pid" 2>/dev/null || true)
|
||||
kill "-$signal" "$pid" 2>/dev/null || true
|
||||
}
|
||||
|
||||
run_with_timeout() {
|
||||
local timeout_seconds="$1"
|
||||
shift
|
||||
if [ "$timeout_seconds" -le 0 ]; then
|
||||
"$@"
|
||||
return $?
|
||||
fi
|
||||
|
||||
"$@" &
|
||||
local command_pid=$!
|
||||
local start_seconds
|
||||
start_seconds="$(date +%s)"
|
||||
while kill -0 "$command_pid" 2>/dev/null; do
|
||||
local now_seconds
|
||||
now_seconds="$(date +%s)"
|
||||
if [ $((now_seconds - start_seconds)) -ge "$timeout_seconds" ]; then
|
||||
echo "::warning::Command timed out after ${timeout_seconds}s: $*"
|
||||
collect_macos_desktop_diagnostics "timeout"
|
||||
terminate_process_tree "$command_pid"
|
||||
wait "$command_pid" 2>/dev/null || true
|
||||
return 124
|
||||
fi
|
||||
sleep 10
|
||||
done
|
||||
wait "$command_pid"
|
||||
}
|
||||
|
||||
run_tauri_build() {
|
||||
run_with_timeout "$TAURI_BUILD_TIMEOUT_SECONDS" \
|
||||
pnpm tauri build \
|
||||
--features desktop-runtime \
|
||||
--target "${{ matrix.rust_target }}" \
|
||||
--bundles "${{ matrix.tauri_bundles }}"
|
||||
}
|
||||
|
||||
status=0
|
||||
for attempt in $(seq 1 "$TAURI_BUNDLE_ATTEMPTS"); do
|
||||
echo "Tauri desktop build attempt $attempt/$TAURI_BUNDLE_ATTEMPTS"
|
||||
if run_tauri_build; then
|
||||
status=0
|
||||
break
|
||||
else
|
||||
status=$?
|
||||
fi
|
||||
|
||||
echo "::warning::Tauri desktop build attempt $attempt/$TAURI_BUNDLE_ATTEMPTS failed with exit code $status."
|
||||
collect_macos_desktop_diagnostics "attempt-${attempt}"
|
||||
if [ "$attempt" -lt "$TAURI_BUNDLE_ATTEMPTS" ]; then
|
||||
sleep 20
|
||||
fi
|
||||
done
|
||||
|
||||
exit "$status"
|
||||
|
||||
- name: Collect macOS desktop diagnostics
|
||||
if: failure() && startsWith(matrix.platform, 'macos-')
|
||||
env:
|
||||
DESKTOP_DIAGNOSTICS_PLATFORM: ${{ matrix.platform }}
|
||||
DESKTOP_DIAGNOSTICS_RUST_TARGET: ${{ matrix.rust_target }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
bash "${DESKTOP_DIAGNOSTICS_SCRIPT:-$GITHUB_WORKSPACE/.github/scripts/collect-macos-desktop-diagnostics.sh}" failure || true
|
||||
|
||||
- name: Upload macOS desktop diagnostics
|
||||
if: failure() && startsWith(matrix.platform, 'macos-')
|
||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
|
||||
with:
|
||||
name: desktop-diagnostics-${{ matrix.platform }}
|
||||
path: |
|
||||
dist/desktop-diagnostics/**
|
||||
apps/desktop/src-tauri/target/${{ matrix.rust_target }}/release/bundle/dmg/**
|
||||
apps/desktop/src-tauri/target/${{ matrix.rust_target }}/release/bundle/macos/**
|
||||
apps/desktop/src-tauri/target/release/bundle/dmg/**
|
||||
apps/desktop/src-tauri/target/release/bundle/macos/**
|
||||
if-no-files-found: ignore
|
||||
include-hidden-files: true
|
||||
|
||||
- name: Sign Windows desktop artifacts
|
||||
if: matrix.platform == 'windows-x64' && env.WINDOWS_SIGNING_ENABLED == 'true'
|
||||
@@ -813,7 +1044,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
ref: ${{ needs.prepare.outputs.tag }}
|
||||
ref: ${{ needs.prepare.outputs.ref }}
|
||||
|
||||
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
||||
with:
|
||||
@@ -884,7 +1115,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
ref: ${{ needs.prepare.outputs.tag }}
|
||||
ref: ${{ needs.prepare.outputs.ref }}
|
||||
|
||||
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
||||
with:
|
||||
@@ -997,7 +1228,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
ref: ${{ needs.prepare.outputs.tag }}
|
||||
ref: ${{ needs.prepare.outputs.ref }}
|
||||
|
||||
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
|
||||
|
||||
@@ -1049,7 +1280,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
ref: ${{ needs.prepare.outputs.tag }}
|
||||
ref: ${{ needs.prepare.outputs.ref }}
|
||||
|
||||
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
|
||||
|
||||
@@ -1152,7 +1383,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
ref: ${{ needs.prepare.outputs.tag }}
|
||||
ref: ${{ needs.prepare.outputs.ref }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Generate release notes
|
||||
@@ -1258,7 +1489,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
ref: ${{ needs.prepare.outputs.tag }}
|
||||
ref: ${{ needs.prepare.outputs.ref }}
|
||||
|
||||
- uses: pnpm/action-setup@a8198c4bff370c8506180b035930dea56dbd5288 # v5
|
||||
with:
|
||||
@@ -1290,7 +1521,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
ref: ${{ needs.prepare.outputs.tag }}
|
||||
ref: ${{ needs.prepare.outputs.ref }}
|
||||
|
||||
- name: Update Homebrew tap formula
|
||||
env:
|
||||
|
||||
Reference in New Issue
Block a user