Windows Builds

mandatory

Como produzir artefatos Windows por tipo de módulo da Koder Stack. Distingue o que funciona direto no Linux (Go cross-compile, MSI via wixl) do que exige delegar para máquina Windows via WinRM (Flutter desktop). Inclui receita pra k.win.

Windows Builds — Koder Stack

Guia de referência para produzir artefatos Windows a partir de diferentes tipos de módulo da Koder Stack. Distingue o que funciona diretamente no Linux do que requer delegar para uma máquina Windows via WinRM.


Regra: MSIX obrigatório para Flutter desktop com UI Windows

Todo módulo Koder que se enquadra em *ualquer*um dos critérios abaixo *eve*gerar .msix em cada release:

  • Tem app/desktop/ com código Flutter
  • Tem "windows" listado em platforms no koder.toml
  • É um produto com usuário final (app de consumo, SaaS, utilitário) mesmo que o diretório app/desktop/ ainda não exista — o MSIX deve ser incluído assim que o build Windows for adicionado

*ão pular*alegando ausência de máquina Windows — sempre delegar via WinRM para s.win.local (VM local) ou k.win (servidor remoto). Ver §2 abaixo para o fluxo completo.

Módulos Koder com Flutter desktop que precisam de MSIX (lista não exaustiva):

Módulo koder.toml platforms Diretório desktop
dev/store (Koder Hub) android, linux, windows, macos, web app/ (multi-plataforma)
suite/kmail (Kmail) linux, windows, macos, android, ios app/desktop/
suite/dek (Koder Dek) linux, windows, macos app/desktop/
foundation/pass (Koder Pass) android, ios, linux, windows, macos app/

Qualquer módulo novo com "windows" em platforms entra nessa lista automaticamente.


Sumário

Tipo de módulo A partir do Linux? Ferramenta Status
Go service / CLI ✅ Cross-compile direto GOOS=windows go build Produção
Flutter desktop app + MSIX ✅ Via WinRM → s.win.local ou k.win vmwinrm.py + build-msix.ps1 Produção
Installer MSI (para .exe Go) ✅ Cross-compile direto wixl (msitools) Produção
Installer EXE (PowerShell) ✅ Via WinRM vmwinrm.py + ps2exe na VM Produção
MSIX via kpkg ⚠️ Stub kpkg build --msix Não implementado
Koder Koda → .exe ✅ Cross-compile direto nasm + mingw + wine Produção

Máquinas Windows disponíveis

Há duas máquinas Windows acessíveis a partir do ambiente de desenvolvimento:

s.win.local — VM Win10 QEMU no notebook (preferida para builds interativos)

  • OS: Windows 10 22H2 (10.0.19045.0)
  • QCOW2: /home/koder/temp/win10-vm/win10.qcow2
  • WinRM: http://localhost:5985/wsman (NTLM, port-forwarded pelo QEMU)
  • Usuário: koder / koder123
  • Controle Python: /home/koder/temp/win10-vm/vmwinrm.py (WinRM) + vm.py (QMP+VNC)
  • Flutter + VS Build Tools: já instalados via setup-flutter-env.ps1
  • Iniciar VM: bash /home/koder/temp/win10-vm/start-vm.sh

k.win — Windows Server 2019 remoto (para builds CI)

  • OS: Windows Server 2019 (10.0.17763)
  • WinRM: http://187.108.204.239:5985/wsman (NTLM)
  • Usuário: administrador / bKlPn0OkZ}N14\mA@``
  • RDP: 187.108.204.239

Toolchain de WinRM (pywinrm)

O script vmwinrm.py faz a ponte Linux → Windows via pywinrm:

# Instalação (uma vez)
pip install --break-system-packages pywinrm

# Aguardar VM estar disponível
python3 ~/temp/win10-vm/vmwinrm.py wait

# Executar comando PowerShell
python3 ~/temp/win10-vm/vmwinrm.py run "Get-Date"

# Executar script .ps1 local (o script é enviado e executado na VM)
python3 ~/temp/win10-vm/vmwinrm.py script build-msix.ps1

# Upload de arquivo para a VM
python3 ~/temp/win10-vm/vmwinrm.py upload local.zip "C:\\dest.zip"

Para k.win, editar HOST, USER, PASS em vmwinrm.py (ou criar cópia kwin.py):

HOST = "187.108.204.239"
USER = "administrador"
PASS = "bKlPn0OkZ}N14`mA@`"

*roblema conhecido — upload de arquivos grandes:*A técnica de base64 embutido no comando falha para arquivos acima de ~1 MB. Solução: HTTP server no host Linux acessado pela VM em 10.0.2.2:

# Host Linux
python3 -m http.server 8877 --directory ~/temp/win10-vm/

# VM Windows (via vmwinrm.py run)
(New-Object Net.WebClient).DownloadFile('http://10.0.2.2:8877/kmail.zip', 'C:\kmail.zip')

1. Go services e CLIs

Cross-compile 100% funcional a partir de Linux. Nenhuma VM necessária.

GOOS=windows GOARCH=amd64 CGO_ENABLED=0 \
  go build -o dist/meu-binario-windows-amd64.exe ./cmd/meu-binario
  • CGO_ENABLED=0 é obrigatório para cross-compile.
  • Gera PE64 válido executável diretamente no Windows.
  • Testado em: kodersignagent, koderwired, koderdrive, koderkmailserver.

2. Flutter desktop apps + MSIX (via WinRM)

flutter build windows --release requer MSVC — toolchain Windows-only. O mecanismo atual é delegar o build para s.win.local via WinRM.

Fluxo completo

# 1. Iniciar a VM (se não estiver rodando)
bash ~/temp/win10-vm/start-vm.sh

# 2. Aguardar WinRM ficar disponível
python3 ~/temp/win10-vm/vmwinrm.py wait

# 3. Copiar projeto para a VM via HTTP server temporário
cd ~/dev/koder/<area>/<produto>/app/desktop
zip -r /home/koder/temp/win10-vm/projeto.zip .
python3 -m http.server 8877 --directory ~/temp/win10-vm/ &
python3 ~/temp/win10-vm/vmwinrm.py run \
  "(New-Object Net.WebClient).DownloadFile('http://10.0.2.2:8877/projeto.zip', 'C:\\projeto.zip')"
python3 ~/temp/win10-vm/vmwinrm.py run \
  "Expand-Archive 'C:\\projeto.zip' 'C:\\projeto' -Force"
kill %1  # parar http.server

# 4. Executar build MSIX na VM
python3 ~/temp/win10-vm/vmwinrm.py script ~/temp/win10-vm/build-msix.ps1

# 5. Recuperar o MSIX gerado
MSIX_PATH=$(python3 ~/temp/win10-vm/vmwinrm.py run \
  "Get-Content 'C:\\koder-msix-path.txt'")
python3 ~/temp/win10-vm/vmwinrm.py run \
  "[Convert]::ToBase64String([IO.File]::ReadAllBytes('$MSIX_PATH'))" \
  | base64 -d > produto.msix

O script de referência para o build MSIX é ~/temp/win10-vm/build-msix.ps1:

  • Gera certificado auto-assinado (.pfx) para sideloading
  • Executa flutter build windows --release
  • Executa dart pub run msix:create com as opções do produto
  • Salva o caminho do MSIX em C:\koder-msix-path.txt

Configuração do pubspec.yaml (Flutter MSIX)

dependencies:
  msix: ^3.16.7

msix_config:
  display_name: Kmail
  publisher_display_name: Koder Dev
  identity_name: dev.koder.kmail
  msix_version: 1.0.3.0
  capabilities: internetClient,privateNetworkClientServer
  languages: en-us

3. Instaladores MSI (a partir de um .exe Go)

Funciona em Linux via wixl (parte do pacote msitools).

sudo apt-get install msitools wixl

# Script de referência (koder-sign-agent)
products/horizontal/sign/engine/cmd/koder-sign-agent/packaging/build-msi.sh \
  <version> <caminho/para/binario.exe>

Outros módulos com scripts MSI prontos:

  • infra/observe/wire/packaging/scripts/build-packages.sh (Koder Wired)
  • products/horizontal/dek/app/windows/koder-dek.wxs (Koder Dek — manifest manual)

4. Installer EXE PowerShell via ps2exe (via WinRM)

O KoderHubSetup.exe é um script PowerShell compilado com ps2exe na VM Windows. ps2exe gera um executável PE32 Mono/.NET que encapsula o script.

# 1. Copiar script para a VM (via upload ou HTTP server)
python3 ~/temp/win10-vm/vmwinrm.py upload \
  products/dev/store/installer/koder-hub-installer.ps1 \
  "C:\\installer.ps1"

# 2. Compilar EXE na VM
python3 ~/temp/win10-vm/vmwinrm.py run \
  "Invoke-ps2exe C:\\installer.ps1 C:\\KoderHubSetup.exe -requireAdmin -noConsole"

# 3. Baixar o EXE gerado
python3 ~/temp/win10-vm/vmwinrm.py run \
  "[Convert]::ToBase64String([IO.File]::ReadAllBytes('C:\\KoderHubSetup.exe'))" \
  | base64 -d > KoderHubSetup.exe

*otcha ps2exe:*$PSScriptRoot e $MyInvocation.MyCommand.Path são null em executáveis compilados. Use try/catch com fallback $env:TEMP para caminhos de escrita.


5. MSIX via kpkg (não implementado)

kpkg build --msix é um stub — emite warning e sai sem gerar arquivo:

// products/dev/kpkg/internal/builder/builder.go linha ~117:
// TODO: implement MSIX export via makemsix

Para implementar: ver meta/docs/stack/specs/kpkg/format.kmd (seção "export targets → msix").


6. Koder Koda → PE64 (executável Windows)

Cross-compile funcional a partir de Linux com nasm + MinGW:

sudo apt-get install nasm mingw-w64 wine-stable

engines/lang/lang/scripts/build-win64-prog.sh hello.kd -o hello.exe
wine hello.exe  # valida o .exe

Referências:

  • engines/lang/lang/scripts/build-win64-prog.sh
  • engines/lang/lang/self-hosted/lib/win64_syscall_shim.asm
  • Teste de regressão: engines/lang/lang/tests/regression/018-win64-cross-compile.test.sh

7. Setup da VM Windows (one-time)

O ambiente Flutter na s.win.local já está instalado. Para reconfigurar do zero:

python3 ~/temp/win10-vm/vmwinrm.py script \
  ~/temp/win10-vm/setup-flutter-env.ps1

O script instala: Chocolatey, Git, Flutter SDK estável, VS Build Tools 2022 (workloads: Desktop C++ + Windows 11 SDK), dart pub global activate msix.


8. Histórico de builds Windows realizados

Produto Versão Tipo Mecanismo
Koder Hub v2.29.15–17 MSIX WinRM → s.win.local → build-msix.ps1
Koder Hub v2.29.17–18 EXE installer WinRM → s.win.local → ps2exe

9. Registrar runner Windows no Flow (opcional — para CI/CD)

Para builds automáticos via Gitea Actions sem intervenção manual:

# .gitea/workflows/store-release.yml
store-publish-win:
  runs-on: windows-latest
  steps:
    - uses: subosito/flutter-action@v2
    - run: flutter pub get && flutter build windows --release
    - run: dart run msix:create

Registrar runner:

# No Windows, após instalar Gitea Actions runner:
./act_runner register \
  --instance https://flow.koder.dev \
  --token <RUNNER_TOKEN> \
  --labels windows-latest,windows,windows-amd64

*tatus atual* runner windows-latest NÃO está registrado no Flow.

Source: ../home/koder/dev/koder/meta/docs/stack/policies/windows-builds.kmd