Skip to content

chore: release v1.2.7 #3069

chore: release v1.2.7

chore: release v1.2.7 #3069

Workflow file for this run

name: CI
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
permissions:
contents: read
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
# Core package tests
core:
runs-on: ubuntu-latest
name: Core Package
timeout-minutes: 20
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version-file: ".bun-version"
- name: Cache Bun dependencies
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-
- name: Install dependencies
run: |
set -e
bun install --frozen-lockfile || (echo "bun install failed, clearing cache and retrying..." && (bun pm cache rm || bun pm cache clean || true) && bun install --frozen-lockfile)
- name: TypeScript check
run: cd packages/core && bun run tsc --noEmit
- name: Large-store performance budgets
run: bun run test:perf
- name: Locale parity check
run: bun run i18n:check
- name: Schema and release workflow governance checks
run: bun run test:governance
- name: README heading parity check
run: bun run docs:check-readme
- name: Store image asset check
run: bash scripts/ci/validate-store-image-assets.sh
- name: AppStream metainfo locale check
run: python3 scripts/ci/validate-appstream-locales.py
- name: Workflow JSON newline check
run: node scripts/ci/validate-workflow-json-newlines.js
- name: Package-lock override sync check
run: |
node scripts/ci/check-package-lock-sync.js packages/core/package.json packages/core/package-lock.json --check-overrides
node scripts/ci/check-package-lock-sync.js apps/desktop/package.json apps/desktop/package-lock.json --check-overrides
node scripts/ci/check-mobile-foss-lock-sync.js
- name: Google Play listing metadata check
run: |
python3 scripts/ci/prepare-google-play-listing-metadata.test.py
python3 scripts/ci/prepare-google-play-listing-metadata.py \
metadata \
/tmp/mindwtr-play-listing-metadata.json
- name: Store changelog length check
run: node scripts/ci/check-changelog-length.js
- name: App Store listing metadata check
run: |
python3 scripts/ci/validate-fastlane-metadata.test.py
FASTLANE_METADATA_DIR=/tmp/mindwtr-fastlane-metadata scripts/ci/prepare-fastlane-metadata.sh
- name: iOS App Intents availability check
run: node scripts/ci/validate-ios-app-intents-availability.js
- name: Apple property list syntax check
run: python3 scripts/ci/validate-apple-plists.py
- name: Run unit tests
run: bun run --filter @mindwtr/core test -- --coverage --coverage.thresholds.lines=70 --coverage.thresholds.statements=70 --coverage.thresholds.functions=50 --coverage.thresholds.branches=50
- name: Core coverage summary
if: always()
run: node scripts/ci/write-coverage-summary.js "Core Coverage" packages/core/coverage/coverage-summary.json --min-lines=70 --min-statements=70 --min-functions=50 --min-branches=50
- name: Upload core coverage artifact
if: always()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: core-coverage
path: packages/core/coverage
if-no-files-found: ignore
# Compile and execute the actual Swift/Objective-C CloudKit Task mappers.
native-schema:
runs-on: macos-15
name: Native Task Schema Contracts
timeout-minutes: 10
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version-file: ".bun-version"
- name: Native synced field parity check
run: bun run schema:check
# Desktop app build and tests (Tauri)
desktop:
runs-on: ubuntu-latest
name: Desktop App (Tauri)
timeout-minutes: 45
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Install system dependencies (Tauri)
run: |
set -euo pipefail
# GitHub-hosted Ubuntu runners sometimes point apt at a flaky Azure
# mirror, but the canonical Ubuntu archive can also stall. Try the
# runner's default mirror first, then alternate with the archive
# fallback on retry.
APT_MIRROR_BACKUP=""
if [ -f /etc/apt/apt-mirrors.txt ]; then
APT_MIRROR_BACKUP="$(mktemp)"
sudo cp /etc/apt/apt-mirrors.txt "$APT_MIRROR_BACKUP"
fi
# The runner image also carries optional Microsoft apt feeds that are
# unrelated to Tauri. If those feeds return 403, apt-get update fails
# before the Ubuntu packages below can install.
mapfile -t MICROSOFT_APT_SOURCES < <(grep -rl 'packages.microsoft.com' /etc/apt/sources.list /etc/apt/sources.list.d 2>/dev/null || true)
for source_file in "${MICROSOFT_APT_SOURCES[@]}"; do
sudo mv "$source_file" "$source_file.disabled"
done
APT_OPTIONS=(
-o Acquire::Retries=3
-o Acquire::http::Timeout=30
-o Acquire::https::Timeout=30
)
APT_PACKAGES=(
libwebkit2gtk-4.1-dev
libappindicator3-dev
librsvg2-dev
patchelf
libasound2-dev
libssl-dev
)
for attempt in 1 2 3; do
if [ -n "$APT_MIRROR_BACKUP" ]; then
sudo cp "$APT_MIRROR_BACKUP" /etc/apt/apt-mirrors.txt
if [ "$attempt" -eq 2 ]; then
sudo sed -i 's|http://azure.archive.ubuntu.com/ubuntu|https://archive.ubuntu.com/ubuntu|g' /etc/apt/apt-mirrors.txt
fi
fi
if timeout 8m sudo apt-get "${APT_OPTIONS[@]}" update && \
timeout 8m sudo apt-get "${APT_OPTIONS[@]}" install -y "${APT_PACKAGES[@]}"; then
exit 0
fi
if [ "$attempt" -eq 3 ]; then
echo "Tauri system dependency install failed after $attempt attempts" >&2
exit 1
fi
echo "Tauri system dependency install failed on attempt $attempt, retrying..." >&2
sudo apt-get clean
sudo rm -rf /var/lib/apt/lists/*
sleep 10
done
- name: Setup Rust
uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
- name: Ensure Rust toolchain (retry)
shell: bash
run: |
for attempt in 1 2 3; do
if rustup toolchain install stable --profile minimal --no-self-update && rustup default stable; then
exit 0
fi
if [ "$attempt" -eq 3 ]; then
echo "Rust toolchain setup failed after $attempt attempts" >&2
exit 1
fi
echo "Rust toolchain setup failed on attempt $attempt, retrying..." >&2
sleep 10
done
- name: Cache Rust artifacts
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
with:
workspaces: apps/desktop/src-tauri
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version-file: ".bun-version"
- name: Cache Bun dependencies
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-
- name: Install dependencies
run: bun install --frozen-lockfile
- name: TypeScript check
run: cd apps/desktop && bun run tsc --noEmit
- name: Run tests
run: bun run --filter mindwtr test -- --coverage --coverage.thresholds.lines=50 --coverage.thresholds.statements=50 --coverage.thresholds.functions=45 --coverage.thresholds.branches=50
- name: Desktop coverage summary
if: always()
run: node scripts/ci/write-coverage-summary.js "Desktop Coverage" apps/desktop/coverage/coverage-summary.json --min-lines=50 --min-statements=50 --min-functions=45 --min-branches=50
- name: Upload desktop coverage artifact
if: always()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: desktop-coverage
path: apps/desktop/coverage
if-no-files-found: ignore
- name: Run Rust tests
timeout-minutes: 20
run: bun run native:test
- name: Build Tauri app (debug, no bundle)
timeout-minutes: 20
run: cd apps/desktop && bunx tauri build --debug --no-bundle
# Exercise cfg(windows) persistence and recovery branches with native tests.
desktop-native-windows:
runs-on: windows-2022
name: Desktop Native (Windows)
timeout-minutes: 30
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Ensure Rust toolchain
shell: pwsh
run: |
rustup toolchain install stable --profile minimal --no-self-update
rustup default stable
- name: Cache Rust artifacts
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
with:
workspaces: apps/desktop/src-tauri
- name: Run Windows native tests
env:
# Packaged Windows builds keep the repo-wide static CRT setting, but
# cargo test also links whisper-rs-sys into a test DLL. Its C/C++
# objects use the dynamic CRT, so forcing +crt-static here leaves
# unresolved __imp_* CRT symbols at link time.
RUSTFLAGS: -C target-feature=-crt-static
run: cargo test --locked --manifest-path apps/desktop/src-tauri/Cargo.toml
# Mobile app validation
mobile:
runs-on: ubuntu-latest
name: Mobile App
timeout-minutes: 30
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version-file: ".bun-version"
- name: Cache Bun dependencies
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-
- name: Install dependencies
run: bun install --frozen-lockfile
- name: TypeScript check
run: cd apps/mobile && bunx tsc --noEmit
- name: Expo Doctor check
run: cd apps/mobile && bunx expo-doctor
- name: Mobile tests
run: bun run --filter mobile test:coverage
- name: Mobile coverage summary
if: always()
run: node scripts/ci/write-coverage-summary.js "Mobile Coverage" apps/mobile/coverage/coverage-summary.json --min-lines=38 --min-statements=38 --min-functions=50 --min-branches=50
- name: Upload mobile coverage artifact
if: always()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: mobile-coverage
path: apps/mobile/coverage
if-no-files-found: ignore
cloud-mcp:
runs-on: ubuntu-latest
name: Cloud and MCP Servers
timeout-minutes: 20
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Test owner-only Docker secret handoff
run: scripts/ci/validate-docker-cloud-secret-runtime.sh
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version-file: ".bun-version"
- name: Cache Bun dependencies
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Cloud TypeScript check
run: bun run --filter mindwtr-cloud typecheck
- name: MCP version metadata check
run: |
set -euo pipefail
node - <<'NODE'
const fs = require('fs');
const packageJson = JSON.parse(fs.readFileSync('apps/mcp-server/package.json', 'utf8'));
const serverJson = JSON.parse(fs.readFileSync('apps/mcp-server/server.json', 'utf8'));
const version = packageJson.version;
const failures = [];
if (!version) {
failures.push('apps/mcp-server/package.json: missing version');
}
if (serverJson.version !== version) {
failures.push(`apps/mcp-server/server.json: expected ${version}, got ${serverJson.version || '<missing>'}`);
}
if (!Array.isArray(serverJson.packages)) {
failures.push('apps/mcp-server/server.json: missing packages array');
} else {
for (const entry of serverJson.packages) {
if (entry.version !== version) {
failures.push(
`apps/mcp-server/server.json package ${entry.identifier || entry.name || '<unknown>'}: expected ${version}, got ${entry.version || '<missing>'}`
);
}
}
}
if (failures.length) {
console.error('MCP npm package and registry metadata versions must match.');
console.error(failures.join('\n'));
process.exit(1);
}
console.log(`Verified MCP package and registry metadata use ${version}.`);
NODE
- name: MCP TypeScript check
run: bun run --filter mindwtr-mcp typecheck
- name: Cloud tests
run: bun run --filter mindwtr-cloud test:coverage
- name: Cloud coverage summary
if: always()
# Bun's LCOV reporter for cloud/mcp currently emits line/function data but no BRF/BRH branch records.
# Keep statement gates as an explicit LCOV line proxy and add a real branch gate when the reporter exposes it.
run: node scripts/ci/write-lcov-summary.js "Cloud Coverage" apps/cloud/coverage/lcov.info --include-prefix=src/ --min-lines=70 --min-statements=70 --min-functions=50
- name: Upload cloud coverage artifact
if: always()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cloud-coverage
path: apps/cloud/coverage
if-no-files-found: ignore
- name: MCP tests
run: bun run --filter mindwtr-mcp test:coverage
- name: MCP coverage summary
if: always()
# Bun's LCOV reporter for cloud/mcp currently emits line/function data but no BRF/BRH branch records.
# Keep statement gates as an explicit LCOV line proxy and add a real branch gate when the reporter exposes it.
run: node scripts/ci/write-lcov-summary.js "MCP Coverage" apps/mcp-server/coverage/lcov.info --include-prefix=src/ --min-lines=70 --min-statements=70 --min-functions=50
- name: MCP core adapter coverage floor
if: always()
run: node scripts/ci/write-lcov-summary.js "MCP core-adapter.ts Coverage" apps/mcp-server/coverage/lcov.info --include-prefix=src/core-adapter.ts --min-lines=53 --min-statements=53 --min-functions=60
- name: MCP paths coverage floor
if: always()
run: node scripts/ci/write-lcov-summary.js "MCP paths.ts Coverage" apps/mcp-server/coverage/lcov.info --include-prefix=src/paths.ts --min-lines=29 --min-statements=29 --min-functions=17
- name: Upload MCP coverage artifact
if: always()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: mcp-coverage
path: apps/mcp-server/coverage
if-no-files-found: ignore
e2e:
runs-on: ubuntu-latest
name: E2E (Web)
timeout-minutes: 30
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version-file: ".bun-version"
- name: Cache Bun dependencies
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Drop unused Microsoft apt repos
# packages.microsoft.com intermittently serves invalid clearsigned
# indexes, which fails the apt update inside `playwright install
# --with-deps`. The E2E job never installs from these repos; same
# workaround as the desktop build job.
run: |
mapfile -t MICROSOFT_APT_SOURCES < <(grep -rl 'packages.microsoft.com' /etc/apt/sources.list /etc/apt/sources.list.d 2>/dev/null || true)
for source_file in "${MICROSOFT_APT_SOURCES[@]}"; do
sudo mv "$source_file" "$source_file.disabled"
done
- name: Install Playwright browsers
run: bunx playwright install --with-deps chromium
- name: Run E2E tests
run: bun run test:e2e
- name: Upload Playwright HTML report
if: failure()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: playwright-report
path: playwright-report
if-no-files-found: ignore
- name: Upload Playwright test results
if: failure()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: playwright-test-results
path: test-results
if-no-files-found: ignore
# Lint check
lint:
runs-on: ubuntu-latest
name: Code Quality
timeout-minutes: 20
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version-file: ".bun-version"
- name: Cache Bun dependencies
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Check for lint errors (core)
run: bun run --filter @mindwtr/core lint
- name: Check for lint errors (desktop)
run: cd apps/desktop && bun run lint
- name: Check for lint errors (mobile)
run: cd apps/mobile && bun run lint
- name: Check for lint errors (cloud)
run: bun run --filter mindwtr-cloud lint
- name: Check for lint errors (mcp)
run: bun run --filter mindwtr-mcp lint