Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
python_embedded/python_dependencies/kaleido/executable/bin/kaleido.exe filter=lfs diff=lfs merge=lfs -text
python_embedded/python_dependencies/**/*.pyd filter=lfs diff=lfs merge=lfs -text
9 changes: 9 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
## Summary

Describe what changed and why.

## Checklist

- [ ] I ran required checks locally.
- [ ] I did not add forbidden/private artifacts to this PR.

78 changes: 78 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

permissions:
contents: read

jobs:
quality-gates:
name: community-quality-gates
runs-on: windows-latest
steps:
- name: Enable Git long paths
shell: pwsh
run: git config --global core.longpaths true

- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 1
lfs: false

- name: Setup Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: "20"
cache: npm

- name: Setup Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: "3.12"

- name: Setup Rust
uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable

- name: Install JS dependencies
run: npm ci --legacy-peer-deps --no-audit --no-fund

- name: Bootstrap Python runtime
shell: pwsh
run: ./scripts/bootstrap-python.ps1

- name: Typecheck
run: npm run -s typecheck

- name: Build frontend
env:
NODE_OPTIONS: --max-old-space-size=4096
run: npm run -s build

- name: Rust check
run: cargo check --manifest-path src-tauri/Cargo.toml

- name: Rust tests
shell: pwsh
run: ./scripts/cargo-test-win.ps1

- name: License summary sync check
run: npm run -s license:summary:check

- name: Isolation allowlist check
run: npm run -s isolation:allowlist:check

- name: Forbidden path hygiene check
shell: pwsh
run: |
$matches = git ls-files | Where-Object {
$_ -match "^(backup/|old_documentation/|_documentation/|memory/|memory_db/|RNA_seq/|retired_python_files/|Screenshot .+\.png$|playwright-report/|edgedriver_win|\.env$|\.env\.production$|\.claude/|AGENTS\.md$|CLAUDE\.md$|\.mcp\.json$|.*\.pfx$|.*\.key$|.*\.Rhistory$|\.pybiomart\.sqlite$|\.tmp-vitest-report\.json$|(?:.*/)?\.ipynb_checkpoints/|python_embedded/python_dependencies/|python_embedded/python\.exe|python_embedded/python312\.dll|python_embedded/.*\.pyd$|python_embedded/.*\.dll$|python_embedded/.*embed.*\.zip$|python_embedded/.*runtime.*\.zip$|^_test_validation/)"
}
if ($matches) {
$matches | ForEach-Object { Write-Host "FORBIDDEN: $_" }
throw "Forbidden tracked paths detected in CI"
}
136 changes: 136 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
name: Release

on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
release_tag:
description: "Version tag to release (for example v0.1.24)"
required: true
type: string
draft_release:
description: "Publish as draft release (recommended for smoke)"
required: false
default: "false"
type: choice
options:
- "false"
- "true"

permissions:
contents: write

jobs:
windows-release:
name: build-and-publish-windows
runs-on: windows-latest
env:
NODE_VERSION: "20"
PYTHON_VERSION: "3.12"
steps:
- name: Enable Git long paths
shell: pwsh
run: git config --global core.longpaths true

- name: Resolve and validate release tag
id: meta
shell: pwsh
run: |
$tag = if ("${{ github.event_name }}" -eq "workflow_dispatch") { "${{ inputs.release_tag }}" } else { "${{ github.ref_name }}" }
$tag = $tag.Trim()
if ($tag -notmatch '^v\d') {
throw "Release workflow requires a v* tag. Got: '$tag'"
}
"release_tag=$tag" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
"release_version=$($tag.TrimStart('v'))" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8

- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
ref: ${{ steps.meta.outputs.release_tag }}
fetch-depth: 0
lfs: false

- name: Setup Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm

- name: Setup Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: ${{ env.PYTHON_VERSION }}

- name: Setup Rust
uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable

- name: Install JS dependencies
run: npm ci --legacy-peer-deps --no-audit --no-fund

- name: Bootstrap Python runtime
shell: pwsh
run: ./scripts/bootstrap-python.ps1

- name: Bootstrap Nuitka builder
shell: pwsh
run: ./scripts/bootstrap-nuitka.ps1

- name: Provision embedded Python runtime
shell: pwsh
run: ./scripts/provision-python-embedded.ps1

- name: Quality gates
run: |
npm run -s typecheck
npm run -s isolation:allowlist:check
npm run -s license:summary:check

- name: Validate release signing secrets
shell: pwsh
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
run: |
if ([string]::IsNullOrWhiteSpace($env:TAURI_SIGNING_PRIVATE_KEY)) {
throw "Missing secret: TAURI_SIGNING_PRIVATE_KEY"
}
if ([string]::IsNullOrWhiteSpace($env:TAURI_SIGNING_PRIVATE_KEY_PASSWORD)) {
throw "Missing secret: TAURI_SIGNING_PRIVATE_KEY_PASSWORD"
}

- name: Build NSIS release artifacts
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
run: npm run -s tauri:build:release:nsis

- name: Generate updater metadata
id: updater
shell: pwsh
run: |
$tag = "${{ steps.meta.outputs.release_tag }}"
$version = "${{ steps.meta.outputs.release_version }}"
$tagDate = git for-each-ref "refs/tags/$tag" --format="%(taggerdate:iso-strict)" | Select-Object -First 1
if ([string]::IsNullOrWhiteSpace($tagDate)) {
$tagDate = git log -1 --format=%cI "$tag"
}
if ([string]::IsNullOrWhiteSpace($tagDate)) {
throw "Could not resolve tag timestamp for $tag"
}
"pub_date=$tagDate" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
node scripts/generate-updater-json.mjs --version $version --tag "$tag" --repo "${{ github.repository }}" --pub-date "$tagDate" --output latest.json
if (-not (Test-Path latest.json)) { throw "latest.json was not generated" }

- name: Publish release assets
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2
with:
tag_name: ${{ steps.meta.outputs.release_tag }}
draft: ${{ github.event_name == 'workflow_dispatch' && inputs.draft_release == 'true' }}
generate_release_notes: true
fail_on_unmatched_files: true
files: |
src-tauri/target/release/bundle/nsis/*
latest.json
Loading
Loading