Skip to content

ci: build for windows arm64#1084

Merged
clementb49 merged 22 commits into
masterfrom
winArm
Apr 11, 2026
Merged

ci: build for windows arm64#1084
clementb49 merged 22 commits into
masterfrom
winArm

Conversation

@clementb49

@clementb49 clementb49 commented Mar 13, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added official Windows ARM64 support across builds and installer.
  • Bug Fixes

    • Improved accessibility output handling with a safe fallback when native support is unavailable.
    • Better runtime architecture detection for ARM64.
  • Chores

    • CI/CD expanded to multi-architecture builds, updated artifact and installer packaging paths, and refined dependency install behavior.
  • Localization

    • Adjusted packaging/upload behavior for generated translation assets.

clementb49 and others added 7 commits April 11, 2026 16:08
Add arm64 architecture to the build matrix using the windows-11-arm
hosted runner, and fix Inno Setup installer to use arm64 install mode
instead of x64compatible for ARM64 builds.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add OPENSSL_VENDORED=1 for ARM64 builds since cryptography 46.x has no
win_arm64 wheel on PyPI and must be compiled from source. Also declare
uv environments to include win_arm64 in lock file resolution, removing
macOS/Linux-only packages from the lock.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace ineffective OPENSSL_VENDORED approach (blocked by cargo --locked
in maturin) with a vcpkg-based OpenSSL installation. The compiled output
is cached under a stable key to avoid recompiling on every run.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add platform marker to exclude accessible-output3 on ARM64 Windows.
Guard the import with try/except so the app runs gracefully when the
package is absent; use_accessible_output now returns False when
accessible_output3 is not installed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Inno Setup does not support the arm64compatible identifier. Use a
preprocessor conditional to set ArchitecturesAllowed=arm64 for ARM64
and {arch}compatible for x86/x64 builds.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
platform.architecture() returns '64bit' on ARM64, causing the updater
to download the x64 installer. Check platform.machine() first to
correctly identify ARM64 Windows.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@clementb49
clementb49 marked this pull request as ready for review April 11, 2026 20:23
@coderabbitai

coderabbitai Bot commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

Adds ARM64 support across Windows CI, dependency selection, runtime accessible-output availability handling, app-architecture detection, and installer preprocessor macros; also adjusts workflow checkout/artifact paths and uv dependency flags.

Changes

Cohort / File(s) Summary
CI & Build Workflows
\.github/workflows/build_app.yml, \.github/workflows/localization.yml, \.github/workflows/ci.yml
Run Windows CI on a matrix (runs-on: ${{ matrix.runner }}) adding windows-11-arm (arm64); arm64-only OpenSSL/vcpkg step; checkout to repo/; update artifact/upload paths to repo/...; change uv sync flags (--compile, removed --no-dev); set UV_NO_DEV: true; add paths-ignore for .pre-commit-config.yaml.
Runtime accessible-output handling
basilisk/accessible_output.py
Add runtime detection for accessible_output3 with _AO3_AVAILABLE; provide _NullAccessibleOutput fallback; require availability + config in use_accessible_output() and short-circuit initialization when not available.
App architecture detection
basilisk/updater.py
Extend BaseUpdater.get_app_architecture() to detect and return arm64 when platform.machine() equals ARM64; keep existing x64/x86 logic otherwise; update docs/examples.
Dependency selection
pyproject.toml
Make accessible-output3 a Windows-only dependency with an environment marker that excludes platform_machine ARM64 (sys_platform == 'win32' and platform_machine != 'ARM64').
Windows installer preprocessor
win_installer.iss
Add preprocessor macros (ArchAllowed, ArchInstall64) derived from AppArch; set ArchitecturesAllowed and ArchitecturesInstallIn64BitMode to use these macros so ARM64 maps to arm64 and non-ARM64 to *compatible/x64compatible.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • AAClause
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'ci: build for windows arm64' directly and accurately describes the main objective of the changeset, which is to add ARM64 Windows architecture support to the CI/build pipeline.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch winArm

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@basilisk/accessible_output.py`:
- Around line 13-15: The module-level availability flags (e.g., _ao3_available)
use lowercase but should follow constant naming convention; rename these flags
to UPPER_SNAKE_CASE (for example _ao3_available -> AO3_AVAILABLE) and update all
usages and imports in this file accordingly (also apply the same change for the
other availability flags referenced around lines 71-72 and 77). Ensure you
preserve the try/except assignment behavior, keep the leading underscore only if
you want module-private visibility (e.g., _AO3_AVAILABLE vs AO3_AVAILABLE) and
update any conditional checks or assignments that reference the old names
(search for occurrences of _ao3_available and the other two flags and replace
them consistently).
- Around line 77-83: When _ao3_available is False the code currently sets
self._accessible_output to None and returns, which allows handle(...,
force=True) to later call self.accessible_output.speak(...) and crash; instead,
replace the None with a safe no-op object so accessible_output.speak is always
callable on unsupported platforms: introduce a simple NullAccessibleOutput (or
similar) and assign it to self._accessible_output in the branch where
_ao3_available is False (preserving display_log behavior), or alternatively
update handle to check self.accessible_output before calling speak; reference
symbols: _ao3_available, display_log, self._accessible_output,
accessible_output.speak, and handle(..., force=True).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: fab532e5-586a-483a-ad19-83176559cb81

📥 Commits

Reviewing files that changed from the base of the PR and between 2e7de49 and e2616d5.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • .github/workflows/build_app.yml
  • .github/workflows/ci.yml
  • .github/workflows/localization.yml
  • basilisk/accessible_output.py
  • basilisk/updater.py
  • pyproject.toml
  • win_installer.iss

Comment thread basilisk/accessible_output.py Outdated
Comment thread basilisk/accessible_output.py Outdated
Introduce _NullAccessibleOutput with no-op speak/braille methods and
assign it instead of None when _AO3_AVAILABLE is False, so
handle(..., force=True) can never crash with AttributeError on
unsupported platforms.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@basilisk/accessible_output.py`:
- Around line 87-93: The accessible_output property is currently annotated as
accessible_output3.outputs.auto.Auto but can also be None (when
use_accessible_output is False) or an instance of _NullAccessibleOutput; define
a small Protocol (e.g., AccessibleOutputLike) that declares the speak(...) and
braille(...) methods, then change the accessible_output property's return type
to Optional[AccessibleOutputLike] (or Union[AccessibleOutputLike, None]) so
callers see the correct contract; update imports to include typing.Protocol and
Optional and use AccessibleOutputLike in the property/type hints instead of
Auto.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0582fb13-cbe7-4202-af57-f7b85064ead9

📥 Commits

Reviewing files that changed from the base of the PR and between e2616d5 and a9e8df7.

📒 Files selected for processing (1)
  • basilisk/accessible_output.py

Comment on lines +87 to +93
if not _AO3_AVAILABLE:
if display_log:
log.debug(
"accessible_output3 is not available on this platform."
)
self._accessible_output = _NullAccessibleOutput()
return

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether callers rely on Auto-specific APIs beyond speak/braille.
rg -nP --type=py '\.accessible_output\.[A-Za-z_]\w*\(' -C2

Repository: SigmaNight/basiliskLLM

Length of output: 703


🏁 Script executed:

# First, let's look at the file to understand the current type annotations
cat -n basilisk/accessible_output.py | head -120

Repository: SigmaNight/basiliskLLM

Length of output: 4350


🏁 Script executed:

# Check for any usages of accessible_output property outside this file
rg -nP --type=py 'accessible_output\.' --glob='!basilisk/accessible_output.py'

Repository: SigmaNight/basiliskLLM

Length of output: 348


🏁 Script executed:

# Also check what accessible_output3 is and what Auto provides
rg -nP --type=py 'accessible_output3|import Auto' basilisk/

Repository: SigmaNight/basiliskLLM

Length of output: 610


Fix type annotation for accessible_output property; it can return None or _NullAccessibleOutput, not just Auto.

The accessible_output property is typed as accessible_output3.outputs.auto.Auto (line 106), but can actually return None (when use_accessible_output is False; see line 99) or _NullAccessibleOutput (line 92). Both _NullAccessibleOutput and Auto provide speak() and braille() methods, which are the only methods actually called (lines 150, 158).

Use a Protocol to properly express this contract:

Proposed typing refactor
-from typing import TYPE_CHECKING
+from typing import TYPE_CHECKING, Protocol
@@
 class _NullAccessibleOutput:
 	"""No-op fallback used when accessible_output3 is unavailable."""
 	def speak(self, text: str) -> None:
 		pass
 	def braille(self, text: str) -> None:
 		pass
+
+
+class _AccessibleOutputBackend(Protocol):
+	def speak(self, text: str) -> None: ...
+	def braille(self, text: str) -> None: ...
@@
 	def __init__(self):
 		"""Initialize the accessible output handler."""
-		self._accessible_output = None
+		self._accessible_output: _AccessibleOutputBackend | None = None
@@
-	def accessible_output(self) -> accessible_output3.outputs.auto.Auto:
+	def accessible_output(self) -> _AccessibleOutputBackend | None:
 		"""Get the Accessible Output instance, initializing it if necessary."""
 		if self._accessible_output is None:
 			self._init_accessible_output(False)
 		return self._accessible_output
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@basilisk/accessible_output.py` around lines 87 - 93, The accessible_output
property is currently annotated as accessible_output3.outputs.auto.Auto but can
also be None (when use_accessible_output is False) or an instance of
_NullAccessibleOutput; define a small Protocol (e.g., AccessibleOutputLike) that
declares the speak(...) and braille(...) methods, then change the
accessible_output property's return type to Optional[AccessibleOutputLike] (or
Union[AccessibleOutputLike, None]) so callers see the correct contract; update
imports to include typing.Protocol and Optional and use AccessibleOutputLike in
the property/type hints instead of Auto.

@clementb49
clementb49 merged commit c5fbd2c into master Apr 11, 2026
13 checks passed
@clementb49
clementb49 deleted the winArm branch April 11, 2026 21:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant