feat: enforce Guanghu-native HoloLake runtime laws
This commit is contained in:
parent
ccee303355
commit
67e6fcdd38
57 changed files with 1765 additions and 1504 deletions
|
|
@ -1,67 +1,59 @@
|
|||
# Git Hooks
|
||||
|
||||
This repo uses Husky hooks from `.husky/`. Those files are the source of truth.
|
||||
This repository uses Husky hooks from `.husky/`. Those files are execution
|
||||
surfaces; GLS-0844 (GHNQG) is the quality authority.
|
||||
|
||||
## Installation
|
||||
|
||||
`pnpm install` runs the `prepare` script and installs the hooks into `.git/hooks`.
|
||||
|
||||
If you need to reinstall them manually:
|
||||
`pnpm install` runs the `prepare` script and installs the hooks into
|
||||
`.git/hooks`. To reinstall them, run:
|
||||
|
||||
```bash
|
||||
pnpm exec husky
|
||||
```
|
||||
|
||||
The hooks expect `node` and `pnpm` to be available. If they are installed via `nvm`, the hooks will try to load `~/.nvm/nvm.sh` automatically.
|
||||
## Native policy
|
||||
|
||||
Documentation/workflow/hook-only commits and pushes are classified before Node tooling is required. Editing those files must not fail merely because `pnpm` is absent from the invoking shell.
|
||||
|
||||
## Policy
|
||||
|
||||
- Commit on `main` or in a detached verification worktree intended for direct promotion.
|
||||
- Commit on `main` or in a detached verification worktree intended for direct
|
||||
promotion.
|
||||
- Push `main -> origin/main` or detached `HEAD -> origin/main` only.
|
||||
- Never use `--no-verify`.
|
||||
- `.codescene-thresholds` is a ratchet. It can only move up.
|
||||
- CodeScene is additive when credentials are already configured. Missing credentials are not a Git transport error and must not prompt account creation, a trial, or a purchase.
|
||||
- The Fifth Domain Router is a separate, explicitly authorized prototype-publication path. Its exact-SHA receipt proves only that an allowlisted branch reached the code channel; it does not replace `main -> main` production promotion.
|
||||
- Run `bash scripts/test-guanghu-native-authority.sh` before repository checks.
|
||||
- Accept only `GHNQG_PASS_100` bound to the exact commit and tree.
|
||||
- Treat any incomplete required gate as `GHNQG_FAIL_0`.
|
||||
- Do not use minimum percentages, weighted scores, waivers, or external
|
||||
analyzers as acceptance states.
|
||||
- The Fifth Domain Router is a separate, explicitly authorized
|
||||
prototype-publication path. Its exact-SHA receipt proves repository
|
||||
publication only; it is not a merge, release, deployment, runtime-health, or
|
||||
persona-birth receipt.
|
||||
|
||||
## Pre-commit
|
||||
|
||||
`.husky/pre-commit` blocks commits unless all applicable checks are true:
|
||||
`.husky/pre-commit` keeps the edit loop fast:
|
||||
|
||||
- staged TypeScript files pass `pnpm lint --quiet`
|
||||
- documentation/workflow/hook-only commits are identified without running application checks
|
||||
- staged TypeScript files pass repository lint;
|
||||
- documentation, workflow, and hook-only commits are classified without
|
||||
requiring application tooling.
|
||||
|
||||
If `CODESCENE_PAT` or `CODESCENE_PROJECT_ID` is missing, the CodeScene portion is skipped, but the rest of the hook still runs. Record CodeScene as `not_run_unconfigured`; do not treat the skip as a failed commit.
|
||||
Passing pre-commit is evidence, not a publication authorization.
|
||||
|
||||
## Pre-push
|
||||
|
||||
`.husky/pre-push` blocks pushes unless all of the following are true:
|
||||
`.husky/pre-push` requires:
|
||||
|
||||
- the current state is `main` or detached `HEAD`
|
||||
- every pushed branch ref is `refs/heads/main -> refs/heads/main` or detached `HEAD -> refs/heads/main`
|
||||
- TypeScript and the Vite build pass
|
||||
- frontend coverage passes
|
||||
- Rust lint and Rust coverage pass when `src-tauri/` changed
|
||||
- the curated Playwright core smoke lane passes via `pnpm playwright:smoke`
|
||||
- current CodeScene Hotspot and Average health are both at or above `.codescene-thresholds`
|
||||
- native-authority contract validation;
|
||||
- TypeScript and Vite build;
|
||||
- frontend tests;
|
||||
- Rust lint, format, and tests when Rust source changed;
|
||||
- the curated Playwright core smoke lane;
|
||||
- a GLS-0844 receipt from the repository-owned executor.
|
||||
|
||||
If the remote CodeScene scores are better than the current thresholds, the hook updates `.codescene-thresholds`, stages it, and stops the push. Commit that file normally, then push again. The hook does not auto-commit or bypass itself.
|
||||
|
||||
If CodeScene credentials are missing, the hook prints a warning and continues after all repository-owned checks pass. This is the intended no-subscription behavior.
|
||||
|
||||
## Legacy Files
|
||||
|
||||
The legacy `pre-commit` file under `.github/hooks/` is archival only. Do not copy it into `.git/hooks`; use Husky and `.husky/` instead. The old design `post-commit` auto-implementation hook was removed because it depended on obsolete one-off scripts. `install-hooks.sh` remains as a reinstall helper that runs Husky.
|
||||
The executor writes its receipt outside the source repository. On BingShuo's
|
||||
workstation, receipts go to JZAO when that volume is mounted.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If a hook cannot find `node` or `pnpm`:
|
||||
|
||||
```bash
|
||||
export NVM_DIR="$HOME/.nvm"
|
||||
. "$NVM_DIR/nvm.sh"
|
||||
nvm use node
|
||||
```
|
||||
|
||||
Then retry the commit or push.
|
||||
If a hook cannot find `node` or `pnpm`, load the configured Node environment
|
||||
and retry. Missing tooling makes the applicable gate incomplete; it does not
|
||||
create a third acceptance state.
|
||||
|
|
|
|||
238
product-source/hololake-platform/.github/SETUP.md
vendored
238
product-source/hololake-platform/.github/SETUP.md
vendored
|
|
@ -1,227 +1,21 @@
|
|||
# CI/CD Setup Guide
|
||||
# HoloLake 代码频道设置
|
||||
|
||||
## Quick Start
|
||||
HoloLake 不需要外部评分平台、外部质量令牌或外部项目编号才能开发、提交和验证。
|
||||
|
||||
### 1. Add GitHub Secrets
|
||||
现行工程权威来自第五域代码频道 `REPO-012` 的注册协议,以及本仓对这些协议的
|
||||
产品层绑定:
|
||||
|
||||
Nel repository GitHub (Settings → Secrets and variables → Actions → New repository secret):
|
||||
- 远端协议注册表:`GLS-PROTOCOL-REGISTRY-20260731`
|
||||
- 产品工程档案:`standards/guanghu-native-engineering-profile.json`
|
||||
- 原生权威检查:`pnpm test:native-authority`
|
||||
- 产品测试:`pnpm test`
|
||||
- 静态检查:`pnpm lint`
|
||||
- 构建验证:`pnpm build`
|
||||
|
||||
**CODESCENE_TOKEN**
|
||||
```
|
||||
<il tuo CodeScene PAT — stesso di ~/.codescene/token>
|
||||
```
|
||||
所有必需门必须绑定同一份源码树并全部完成,才允许形成 `GHNQG_PASS_100`。
|
||||
任一必需门失败、缺失或没有证据,本轮状态就是 `GHNQG_FAIL_0`。测试框架、
|
||||
编译器、代码托管和流水线只是执行这些门的施工条件,不拥有发布、部署或真实
|
||||
状态的裁决权。
|
||||
|
||||
**CODESCENE_PROJECT_ID**
|
||||
Trova l'ID del progetto nella dashboard CodeScene (URL: `https://codescene.io/projects/<PROJECT_ID>/...`)
|
||||
|
||||
**VITE_SENTRY_DSN**
|
||||
```
|
||||
<frontend Sentry DSN used by shipped Tolaria builds>
|
||||
```
|
||||
|
||||
**SENTRY_DSN**
|
||||
```
|
||||
<same DSN as VITE_SENTRY_DSN, passed to the Rust/Tauri build for native crash reporting>
|
||||
```
|
||||
|
||||
**VITE_POSTHOG_KEY**
|
||||
```
|
||||
<PostHog project API key used by shipped Tolaria builds>
|
||||
```
|
||||
|
||||
**VITE_POSTHOG_HOST**
|
||||
```
|
||||
https://eu.i.posthog.com
|
||||
```
|
||||
|
||||
**Windows Authenticode release signing**
|
||||
|
||||
Windows release artifacts can be Authenticode-signed when a trusted code-signing certificate is available. Until Windows certificate provisioning is complete, the release workflow warns and publishes Windows artifacts with Tauri updater signatures only.
|
||||
|
||||
To enable Authenticode, configure a trusted certificate exported as base64 PFX data:
|
||||
|
||||
```
|
||||
WINDOWS_CODE_SIGNING_CERTIFICATE=<base64-encoded pfx>
|
||||
WINDOWS_CODE_SIGNING_CERTIFICATE_PASSWORD=<pfx password>
|
||||
```
|
||||
|
||||
Optional:
|
||||
|
||||
```
|
||||
WINDOWS_CODE_SIGNING_CERTIFICATE_THUMBPRINT=<expected certificate thumbprint>
|
||||
WINDOWS_CODE_SIGNING_TIMESTAMP_URL=https://timestamp.digicert.com
|
||||
```
|
||||
|
||||
Legacy aliases `WINDOWS_CERTIFICATE`, `WINDOWS_CERTIFICATE_PASSWORD`, `WINDOWS_CERTIFICATE_THUMBPRINT`, and `WINDOWS_TIMESTAMP_URL` are still accepted by the signing script. Do not use a self-signed certificate for public releases; Windows Authenticode release signing needs a certificate from a trusted CA or signing service.
|
||||
|
||||
### 2. Enable GitHub Actions
|
||||
|
||||
- Vai su Settings → Actions → General
|
||||
- Assicurati che "Allow all actions and reusable workflows" sia selezionato
|
||||
|
||||
### 3. Configure Branch Protection (Optional ma Raccomandato)
|
||||
|
||||
Settings → Branches → Add branch protection rule:
|
||||
|
||||
**Branch name pattern**: `main`
|
||||
|
||||
Abilita:
|
||||
- ✅ Require status checks to pass before merging
|
||||
- Select: `Tests & Quality Checks`
|
||||
- ✅ Require branches to be up to date before merging
|
||||
- ✅ Do not allow bypassing the above settings
|
||||
|
||||
Questo forza tutti i check a passare prima di poter fare merge su main.
|
||||
|
||||
### 4. Test Locally Prima di Pushare
|
||||
|
||||
```bash
|
||||
# Full test suite
|
||||
pnpm test && cargo test --manifest-path=src-tauri/Cargo.toml
|
||||
|
||||
# Coverage
|
||||
pnpm test:coverage
|
||||
|
||||
# Lint
|
||||
pnpm lint
|
||||
cargo clippy --manifest-path=src-tauri/Cargo.toml
|
||||
|
||||
# Format check
|
||||
cargo fmt --manifest-path=src-tauri/Cargo.toml -- --check
|
||||
```
|
||||
|
||||
## What Gets Checked
|
||||
|
||||
### ✅ Tests
|
||||
- Frontend: Vitest
|
||||
- Backend: `cargo test`
|
||||
|
||||
### 📊 Coverage
|
||||
- Threshold: 70% (lines, functions, branches, statements)
|
||||
- Configurabile in `vite.config.ts`
|
||||
|
||||
### 🏥 Code Health
|
||||
- CodeScene delta analysis
|
||||
- **Fail se code health diminuisce**
|
||||
- Confronta HEAD vs base branch
|
||||
|
||||
### 📡 Telemetry In Release Builds
|
||||
- `release.yml` e `release-stable.yml` devono ricevere `VITE_SENTRY_DSN`, `SENTRY_DSN`, `VITE_POSTHOG_KEY`, `VITE_POSTHOG_HOST`
|
||||
- `VITE_SENTRY_DSN` inizializza il frontend Sentry bundle
|
||||
- `SENTRY_DSN` inizializza Sentry nel binary Rust/Tauri
|
||||
- `VITE_POSTHOG_KEY` / `VITE_POSTHOG_HOST` permettono ai build distribuiti di inizializzare PostHog quando l'utente abilita analytics
|
||||
|
||||
### 📝 Documentation
|
||||
- **Warning se modifichi `src/` o `src-tauri/` ma non aggiorni `docs/`**
|
||||
- Non blocca il merge, solo un reminder
|
||||
- Skip il check con `[skip docs]` nel commit message
|
||||
- Aggiorna docs solo se la modifica invalida qualcosa già documentato
|
||||
|
||||
### 🎨 Lint & Format
|
||||
- ESLint per frontend
|
||||
- Clippy + rustfmt per Rust
|
||||
|
||||
## Workflow File
|
||||
|
||||
Il workflow è in `.github/workflows/ci.yml`.
|
||||
|
||||
**Trigger**:
|
||||
- Push su `main` o `experiment/*`
|
||||
- Pull request verso `main`
|
||||
|
||||
**Runner**: `macos-latest` (necessario per Tauri + Rust)
|
||||
|
||||
## Customization
|
||||
|
||||
### Soglie Coverage
|
||||
|
||||
Modifica `vite.config.ts`:
|
||||
|
||||
```typescript
|
||||
coverage: {
|
||||
thresholds: {
|
||||
lines: 80, // Aumenta se vuoi più coverage
|
||||
functions: 80,
|
||||
branches: 80,
|
||||
statements: 80,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Documentation Check
|
||||
|
||||
Il check **avvisa** (non fallisce) se:
|
||||
1. Modifichi file in `src/` o `src-tauri/`
|
||||
2. NON modifichi nulla in `docs/`
|
||||
|
||||
**Quando aggiornare docs:**
|
||||
- Cambi architettura → aggiorna `docs/ARCHITECTURE.md`
|
||||
- Cambi astrazioni chiave → aggiorna `docs/ABSTRACTIONS.md`
|
||||
- Cambi theme system → aggiorna `docs/THEMING.md`
|
||||
- Bug fix / refactor interno → `[skip docs]` nel commit message
|
||||
|
||||
**Skip il check:**
|
||||
```bash
|
||||
git commit -m "fix: editor scroll bug [skip docs]"
|
||||
```
|
||||
|
||||
### CodeScene Fail Threshold
|
||||
|
||||
Nel workflow, modifica:
|
||||
|
||||
```yaml
|
||||
- name: CodeScene Delta Analysis
|
||||
uses: codescene-oss/codescene-delta-analysis-action@v1
|
||||
with:
|
||||
fail-on-declining-code-health: true # Cambia a false per warning-only
|
||||
minimum-code-health-score: 8.0 # Aggiungi per soglia assoluta
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### CodeScene fails con "Project not found"
|
||||
- Verifica che `CODESCENE_PROJECT_ID` sia corretto
|
||||
- Controlla che il token abbia accesso al progetto
|
||||
|
||||
### Coverage check fails
|
||||
- Verifica che `@vitest/coverage-v8` sia installato: `pnpm add -D @vitest/coverage-v8`
|
||||
- Le soglie sono configurabili in `vite.config.ts`
|
||||
|
||||
### Docs check avvisa anche se non serve aggiornare docs
|
||||
- È solo un warning, non blocca
|
||||
- Skip con `[skip docs]` nel commit message
|
||||
- Oppure ignora — è un reminder, non un requisito
|
||||
|
||||
### Workflow non si attiva
|
||||
- Verifica che il file sia in `.github/workflows/ci.yml`
|
||||
- Controlla che GitHub Actions sia abilitato nelle settings
|
||||
- Il workflow parte solo su push/PR verso `main` o branch `experiment/*`
|
||||
|
||||
## Example CI Pass
|
||||
|
||||
```
|
||||
✅ Run frontend tests
|
||||
✅ Run Rust tests
|
||||
✅ Run frontend coverage (75% lines, 73% functions)
|
||||
✅ CodeScene Delta Analysis (code health: 9.2 → 9.3)
|
||||
✅ Check docs are updated (docs/ARCHITECTURE.md modified)
|
||||
✅ Lint frontend
|
||||
✅ Clippy (Rust)
|
||||
✅ Format check (Rust)
|
||||
```
|
||||
|
||||
## Example CI Warning
|
||||
|
||||
```
|
||||
⚠️ Code files changed but docs/ not updated
|
||||
Changed code files:
|
||||
- src/components/Editor.tsx
|
||||
- src-tauri/src/vault.rs
|
||||
|
||||
If this change affects architecture/abstractions/design documented in docs/,
|
||||
please update the relevant documentation files.
|
||||
|
||||
To skip this check, include [skip docs] in your commit message.
|
||||
```
|
||||
|
||||
Questo è solo un reminder. Se la modifica non invalida la documentazione esistente, puoi ignorarlo o usare `[skip docs]`.
|
||||
机密信息只通过设备安全存储和获准的运行能力使用,不写入仓库、构建产物或
|
||||
同步数据。
|
||||
|
|
|
|||
|
|
@ -1,81 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Pre-commit hook: CodeScene Code Health Check
|
||||
# Copy to .git/hooks/pre-commit and make executable
|
||||
|
||||
set -e
|
||||
|
||||
# Allow bypass with --no-verify or [skip codescene] in commit message
|
||||
if git log -1 --pretty=%B 2>/dev/null | grep -qi '\[skip codescene\]'; then
|
||||
echo "⏭️ CodeScene check skipped (commit message contains [skip codescene])"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "🔍 Running CodeScene Code Health check..."
|
||||
|
||||
# Check if we have staged files to analyze
|
||||
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(ts|tsx|rs)$' || true)
|
||||
|
||||
if [ -z "$STAGED_FILES" ]; then
|
||||
echo "✅ No TypeScript/Rust files staged, skipping CodeScene check"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Get current branch
|
||||
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||
|
||||
# Determine base branch for comparison
|
||||
if [ "$CURRENT_BRANCH" = "main" ]; then
|
||||
BASE_REF="HEAD~1"
|
||||
else
|
||||
BASE_REF="origin/main"
|
||||
fi
|
||||
|
||||
echo " Comparing against: $BASE_REF"
|
||||
|
||||
# Check if we have CodeScene configured (MCP or CLI)
|
||||
CODESCENE_MCP_CONFIG="$HOME/.claude/mcp.json"
|
||||
CODESCENE_TOKEN_FILE="$HOME/.codescene/token"
|
||||
|
||||
if [ ! -f "$CODESCENE_MCP_CONFIG" ] && [ ! -f "$CODESCENE_TOKEN_FILE" ]; then
|
||||
echo "⚠️ CodeScene not configured"
|
||||
echo " Install CodeScene MCP (configured in ~/.claude/mcp.json)"
|
||||
echo " Or place token at ~/.codescene/token"
|
||||
echo " Proceeding without check (use 'git commit --no-verify' to skip this warning)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Simple health check using git diff stats
|
||||
echo " Analyzing code changes..."
|
||||
|
||||
# Get file changes
|
||||
LINES_ADDED=$(git diff --cached --numstat | awk '{sum+=$1} END {print sum}')
|
||||
LINES_REMOVED=$(git diff --cached --numstat | awk '{sum+=$2} END {print sum}')
|
||||
|
||||
# Check for large files (potential complexity)
|
||||
LARGE_FILES=$(git diff --cached --numstat | awk '$1 > 500 || $2 > 500 {print $3}')
|
||||
|
||||
if [ ! -z "$LARGE_FILES" ]; then
|
||||
echo "⚠️ Large file changes detected (>500 lines):"
|
||||
echo "$LARGE_FILES" | sed 's/^/ - /'
|
||||
echo ""
|
||||
echo " Consider:"
|
||||
echo " - Breaking into smaller commits"
|
||||
echo " - Reviewing with Claude Code + CodeScene MCP"
|
||||
echo " - Running: claude 'Review code health of staged changes'"
|
||||
echo ""
|
||||
read -p " Continue anyway? (y/N) " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "❌ Commit aborted"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "✅ CodeScene check passed"
|
||||
echo " +$LINES_ADDED -$LINES_REMOVED lines"
|
||||
echo ""
|
||||
echo " 💡 For detailed code health analysis, run:"
|
||||
echo " claude 'Check code health of this commit with CodeScene MCP'"
|
||||
echo ""
|
||||
|
||||
exit 0
|
||||
|
|
@ -1,133 +1,15 @@
|
|||
# CI/CD Setup
|
||||
# HoloLake 原生工程流水线
|
||||
|
||||
## GitHub Actions Workflow
|
||||
流水线执行 HoloLake 已登记的光湖原生工程门,不调用外部评分服务,也不把
|
||||
托管平台的状态当作光湖事实。
|
||||
|
||||
Il workflow `ci.yml` esegue i seguenti check automatici:
|
||||
## 当前执行顺序
|
||||
|
||||
### 1. Tests
|
||||
- Frontend: `pnpm test`
|
||||
- Rust backend: `cargo test`
|
||||
1. 回读产品工程档案和固定的 `REPO-012` 协议注册表提交。
|
||||
2. 验证第三方评分规则没有重新进入现行权威面。
|
||||
3. 验证人格系统输入、类型化输出、能力登记和证据回执合同。
|
||||
4. 运行产品单元、集成、格式、静态检查、脚本语法和构建门。
|
||||
5. 对精确提交与源码树汇总 `GHNQG_PASS_100` 或 `GHNQG_FAIL_0`。
|
||||
|
||||
### 2. Test Coverage
|
||||
- Frontend: vitest con coverage reporting
|
||||
- Upload automatico su Codecov dai report LCOV frontend + Rust
|
||||
- Threshold configurabile in `vitest.config.ts`
|
||||
|
||||
### 3. Code Health (CodeScene)
|
||||
- Delta analysis su ogni PR/push
|
||||
- Fail se il code health diminuisce
|
||||
- Richiede secrets configurati (vedi sotto)
|
||||
|
||||
### 4. Documentation Check
|
||||
- Verifica che se cambia codice in `src/` o `src-tauri/`, anche `docs/` viene aggiornato
|
||||
- **Warning only** — non blocca il merge, solo un reminder
|
||||
- Skip con `[skip docs]` nel commit message
|
||||
- Aggiorna docs solo se la modifica invalida architettura/astrazioni/design già documentati
|
||||
|
||||
### 5. Lint & Format
|
||||
- ESLint per frontend
|
||||
- Clippy + rustfmt per Rust
|
||||
|
||||
## Setup Required
|
||||
|
||||
### CodeScene Secrets
|
||||
Aggiungi questi secrets nel repository GitHub (Settings → Secrets → Actions):
|
||||
|
||||
```
|
||||
CODESCENE_TOKEN=<your-codescene-pat>
|
||||
CODESCENE_PROJECT_ID=<your-project-id>
|
||||
```
|
||||
|
||||
Il PAT di CodeScene è lo stesso che usi localmente (~/.codescene/token).
|
||||
Il project ID lo trovi nella dashboard CodeScene.
|
||||
|
||||
### Codecov Setup
|
||||
- Installa/attiva il repo in Codecov una volta sola tramite GitHub App / import del repository.
|
||||
- Nessun `CODECOV_TOKEN` richiesto in GitHub Actions: `ci.yml` usa OIDC (`id-token: write` + `use_oidc: true`).
|
||||
- Il workflow carica `coverage/lcov.info` (Vitest) e `coverage/rust.lcov` (cargo-llvm-cov).
|
||||
- L'action Codecov resta con integrity validation attiva. Se Codecov ruota la chiave GPG del CLI, aggiorna il pin dell'action invece di usare `skip_validation`.
|
||||
|
||||
### Telemetry Secrets For Release Builds
|
||||
Aggiungi anche questi secrets per i workflow `release.yml` e `release-stable.yml`:
|
||||
|
||||
```
|
||||
VITE_SENTRY_DSN=<frontend sentry dsn>
|
||||
SENTRY_DSN=<same dsn for rust/native crash reporting>
|
||||
VITE_POSTHOG_KEY=<posthog project api key>
|
||||
VITE_POSTHOG_HOST=https://eu.i.posthog.com
|
||||
```
|
||||
|
||||
Senza questi valori, i build distribuiti possono mantenere i toggle telemetry nelle Settings ma non inizializzare davvero PostHog/Sentry.
|
||||
|
||||
### Windows Authenticode Secrets For Release Builds
|
||||
Windows alpha e stable release builds usano sempre le firme Tauri updater. Se i secret Authenticode sono presenti, il workflow firma anche gli installer Windows e verifica le firme; se mancano, emette un warning e pubblica gli artifact Windows senza Authenticode finche' il certificato non e' pronto.
|
||||
|
||||
```
|
||||
WINDOWS_CODE_SIGNING_CERTIFICATE=<base64-encoded pfx>
|
||||
WINDOWS_CODE_SIGNING_CERTIFICATE_PASSWORD=<pfx password>
|
||||
```
|
||||
|
||||
Opzionale:
|
||||
|
||||
```
|
||||
WINDOWS_CODE_SIGNING_CERTIFICATE_THUMBPRINT=<expected thumbprint>
|
||||
WINDOWS_CODE_SIGNING_TIMESTAMP_URL=https://timestamp.digicert.com
|
||||
```
|
||||
|
||||
Il certificato deve essere un certificato di code signing trusted; un certificato self-signed non e' adatto per i release artifact pubblici.
|
||||
|
||||
### Coverage Thresholds
|
||||
Configura in `vitest.config.ts`:
|
||||
|
||||
```typescript
|
||||
export default defineConfig({
|
||||
test: {
|
||||
coverage: {
|
||||
lines: 80,
|
||||
functions: 80,
|
||||
branches: 80,
|
||||
statements: 80,
|
||||
// Fail CI se sotto threshold
|
||||
thresholds: {
|
||||
lines: 80,
|
||||
functions: 80,
|
||||
branches: 80,
|
||||
statements: 80
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Local Testing
|
||||
|
||||
Prima di pushare, puoi testare localmente:
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
pnpm test && cargo test
|
||||
|
||||
# Check coverage
|
||||
pnpm test:coverage
|
||||
|
||||
# Lint
|
||||
pnpm lint
|
||||
cargo clippy
|
||||
cargo fmt --check
|
||||
|
||||
# CodeScene (local)
|
||||
codescene delta-analysis --base-revision origin/main
|
||||
```
|
||||
|
||||
## Workflow Triggers
|
||||
|
||||
- **Push**: su `main`
|
||||
- **Pull Request**: verso `main`
|
||||
- **Manuale**: `workflow_dispatch`
|
||||
|
||||
Nota: l'upload a Codecov gira su push a `main` e sulle PR dello stesso repository. Le PR da fork saltano l'upload per evitare problemi di permessi OIDC.
|
||||
|
||||
## Status Checks
|
||||
|
||||
Tutti i check devono passare prima di poter fare merge.
|
||||
Se un check fallisce, vedrai il dettaglio nei logs di GitHub Actions.
|
||||
流水线通过只证明该源码树完成了已声明的工程门,不证明已经上传、部署、在线、
|
||||
出生或取得服务器权限。部署与运行状态必须由目标节点自己的回执独立证明。
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Full history for CodeScene
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa
|
||||
|
|
@ -72,43 +72,8 @@ jobs:
|
|||
if: steps.docs-changes.outputs.should-build == 'true'
|
||||
run: pnpm docs:build
|
||||
|
||||
# ── 1. Code Health (CodeScene — Hotspot + Average Code Health gates) ──
|
||||
# Enforces minimum floors on BOTH hotspot and average code health.
|
||||
# Thresholds come from .codescene-thresholds so CI and local hooks match.
|
||||
- name: Code Health gates
|
||||
env:
|
||||
CODESCENE_PAT: ${{ secrets.CODESCENE_PAT }}
|
||||
CODESCENE_PROJECT_ID: ${{ secrets.CODESCENE_PROJECT_ID }}
|
||||
run: |
|
||||
HOTSPOT_THRESHOLD=$(grep '^HOTSPOT_THRESHOLD=' .codescene-thresholds | cut -d= -f2)
|
||||
AVERAGE_THRESHOLD=$(grep '^AVERAGE_THRESHOLD=' .codescene-thresholds | cut -d= -f2)
|
||||
API_RESPONSE=$(curl -sf \
|
||||
-H "Authorization: Bearer $CODESCENE_PAT" \
|
||||
-H "Accept: application/json" \
|
||||
"https://api.codescene.io/v2/projects/$CODESCENE_PROJECT_ID")
|
||||
HOTSPOT_SCORE=$(echo "$API_RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['analysis']['hotspot_code_health']['now'])")
|
||||
AVERAGE_SCORE=$(echo "$API_RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['analysis']['code_health']['now'])")
|
||||
echo "Hotspot Code Health: $HOTSPOT_SCORE (threshold: $HOTSPOT_THRESHOLD)"
|
||||
echo "Average Code Health: $AVERAGE_SCORE (threshold: $AVERAGE_THRESHOLD)"
|
||||
python3 -c "
|
||||
hotspot = float('$HOTSPOT_SCORE')
|
||||
average = float('$AVERAGE_SCORE')
|
||||
ht = float('$HOTSPOT_THRESHOLD')
|
||||
at = float('$AVERAGE_THRESHOLD')
|
||||
failed = False
|
||||
if hotspot < ht:
|
||||
print(f'❌ Hotspot Code Health {hotspot:.2f} is below threshold {ht}')
|
||||
failed = True
|
||||
else:
|
||||
print(f'✅ Hotspot Code Health {hotspot:.2f} ≥ {ht}')
|
||||
if average < at:
|
||||
print(f'❌ Average Code Health {average:.2f} is below threshold {at}')
|
||||
failed = True
|
||||
else:
|
||||
print(f'✅ Average Code Health {average:.2f} ≥ {at}')
|
||||
if failed:
|
||||
exit(1)
|
||||
"
|
||||
- name: Guanghu native authority contract
|
||||
run: pnpm test:native-authority && pnpm test:native-core
|
||||
|
||||
# ── 2. Documentation check (warning only — does not fail build) ───────
|
||||
- name: Check docs are updated
|
||||
|
|
@ -133,7 +98,7 @@ jobs:
|
|||
run: pnpm lint
|
||||
|
||||
frontend-tests:
|
||||
name: Frontend Tests & Coverage
|
||||
name: Frontend Tests
|
||||
runs-on: macos-15
|
||||
|
||||
steps:
|
||||
|
|
@ -153,25 +118,11 @@ jobs:
|
|||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
# The coverage command runs the canonical frontend test suite.
|
||||
- name: Bundle MCP server resources (required by Tauri build)
|
||||
run: node scripts/bundle-mcp-server.mjs
|
||||
|
||||
- name: Frontend tests + coverage (≥70% lines/functions/branches/statements)
|
||||
run: pnpm test:coverage
|
||||
# Thresholds configured in vite.config.ts — exits non-zero if coverage drops
|
||||
|
||||
- name: Upload frontend coverage to Codecov
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
|
||||
uses: codecov/codecov-action@5975040f7f7d40edaff8d784b576fd65ae95c073
|
||||
with:
|
||||
use_oidc: true
|
||||
fail_ci_if_error: true
|
||||
disable_search: true
|
||||
files: ./coverage/lcov.info
|
||||
flags: frontend
|
||||
verbose: true
|
||||
# OIDC avoids long-lived CODECOV_TOKEN secrets.
|
||||
- name: Frontend tests
|
||||
run: pnpm test
|
||||
|
||||
rust-quality:
|
||||
name: Rust Tests & Quality Checks
|
||||
|
|
@ -196,32 +147,11 @@ jobs:
|
|||
restore-keys: |
|
||||
${{ runner.os }}-cargo-${{ env.RUST_TARGET_CACHE_VERSION }}-
|
||||
|
||||
- name: Install cargo-llvm-cov
|
||||
- name: Install native coverage executor
|
||||
uses: taiki-e/install-action@e5de28abeb52d916c5e5875d54b21a9e738b61ec
|
||||
|
||||
- name: Rust tests + coverage (≥85% lines)
|
||||
run: |
|
||||
mkdir -p coverage
|
||||
cargo llvm-cov \
|
||||
--manifest-path src-tauri/Cargo.toml \
|
||||
--ignore-filename-regex 'lib\.rs|main\.rs|menu\.rs' \
|
||||
--lcov \
|
||||
--output-path coverage/rust.lcov \
|
||||
--fail-under-lines 85
|
||||
# cargo-llvm-cov exits non-zero if line coverage drops below 85%
|
||||
# lib.rs/main.rs/menu.rs are Tauri boilerplate -- not meaningfully unit-testable.
|
||||
|
||||
- name: Upload Rust coverage to Codecov
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
|
||||
uses: codecov/codecov-action@5975040f7f7d40edaff8d784b576fd65ae95c073
|
||||
with:
|
||||
use_oidc: true
|
||||
fail_ci_if_error: true
|
||||
disable_search: true
|
||||
files: ./coverage/rust.lcov
|
||||
flags: rust
|
||||
verbose: true
|
||||
# OIDC avoids long-lived CODECOV_TOKEN secrets.
|
||||
- name: Rust tests
|
||||
run: cargo test --manifest-path src-tauri/Cargo.toml
|
||||
|
||||
- name: Clippy (Rust)
|
||||
run: cargo clippy --manifest-path=src-tauri/Cargo.toml -- -D warnings
|
||||
|
|
@ -229,6 +159,13 @@ jobs:
|
|||
- name: Format check (Rust)
|
||||
run: cargo fmt --manifest-path=src-tauri/Cargo.toml -- --check
|
||||
|
||||
- name: GLS-0844 HoloLake native quality receipt
|
||||
run: |
|
||||
mkdir -p "$RUNNER_TEMP/ghnqg"
|
||||
bash scripts/run-hololake-native-quality-gate.sh \
|
||||
"$RUNNER_TEMP/ghnqg/GHNQG-${GITHUB_SHA}.hldp"
|
||||
grep -Fxq 'result: PASS_100' "$RUNNER_TEMP/ghnqg/GHNQG-${GITHUB_SHA}.hldp"
|
||||
|
||||
linux-build:
|
||||
name: Linux build verification
|
||||
# Keep the normal push CI lane under the 10-minute target. The release
|
||||
|
|
|
|||
Loading…
Reference in a new issue